// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:async/async.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  group('$MethodChannelGoogleMapsFlutter', () {
    late List<String> log;

    setUp(() async {
      log = <String>[];
    });

    /// Initializes a map with the given ID and canned responses, logging all
    /// calls to [log].
    void configureMockMap(
      MethodChannelGoogleMapsFlutter maps, {
      required int mapId,
      required Future<dynamic>? Function(MethodCall call) handler,
    }) {
      maps
          .ensureChannelInitialized(mapId)
          .setMockMethodCallHandler((MethodCall methodCall) {
        log.add(methodCall.method);
        return handler(methodCall);
      });
    }

    Future<void> sendPlatformMessage(
        int mapId, String method, Map<dynamic, dynamic> data) async {
      final ByteData byteData = const StandardMethodCodec()
          .encodeMethodCall(MethodCall(method, data));
      await TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger
          .handlePlatformMessage('plugins.flutter.io/google_maps_$mapId',
              byteData, (ByteData? data) {});
    }

    // Calls each method that uses invokeMethod with a return type other than
    // void to ensure that the casting/nullability handling succeeds.
    //
    // TODO(stuartmorgan): Remove this once there is real test coverage of
    // each method, since that would cover this issue.
    test('non-void invokeMethods handle types correctly', () async {
      const int mapId = 0;
      final MethodChannelGoogleMapsFlutter maps =
          MethodChannelGoogleMapsFlutter();
      configureMockMap(maps, mapId: mapId,
          handler: (MethodCall methodCall) async {
        switch (methodCall.method) {
          case 'map#getLatLng':
            return <dynamic>[1.0, 2.0];
          case 'markers#isInfoWindowShown':
            return true;
          case 'map#getZoomLevel':
            return 2.5;
          case 'map#takeSnapshot':
            return null;
        }
      });

      await maps.getLatLng(const ScreenCoordinate(x: 0, y: 0), mapId: mapId);
      await maps.isMarkerInfoWindowShown(const MarkerId(''), mapId: mapId);
      await maps.getZoomLevel(mapId: mapId);
      await maps.takeSnapshot(mapId: mapId);
      // Check that all the invokeMethod calls happened.
      expect(log, <String>[
        'map#getLatLng',
        'markers#isInfoWindowShown',
        'map#getZoomLevel',
        'map#takeSnapshot',
      ]);
    });
    test('markers send drag event to correct streams', () async {
      const int mapId = 1;
      final Map<dynamic, dynamic> jsonMarkerDragStartEvent = <dynamic, dynamic>{
        'mapId': mapId,
        'markerId': 'drag-start-marker',
        'position': <double>[1.0, 1.0]
      };
      final Map<dynamic, dynamic> jsonMarkerDragEvent = <dynamic, dynamic>{
        'mapId': mapId,
        'markerId': 'drag-marker',
        'position': <double>[1.0, 1.0]
      };
      final Map<dynamic, dynamic> jsonMarkerDragEndEvent = <dynamic, dynamic>{
        'mapId': mapId,
        'markerId': 'drag-end-marker',
        'position': <double>[1.0, 1.0]
      };

      final MethodChannelGoogleMapsFlutter maps =
          MethodChannelGoogleMapsFlutter();
      maps.ensureChannelInitialized(mapId);

      final StreamQueue<MarkerDragStartEvent> markerDragStartStream =
          StreamQueue<MarkerDragStartEvent>(
              maps.onMarkerDragStart(mapId: mapId));
      final StreamQueue<MarkerDragEvent> markerDragStream =
          StreamQueue<MarkerDragEvent>(maps.onMarkerDrag(mapId: mapId));
      final StreamQueue<MarkerDragEndEvent> markerDragEndStream =
          StreamQueue<MarkerDragEndEvent>(maps.onMarkerDragEnd(mapId: mapId));

      await sendPlatformMessage(
          mapId, 'marker#onDragStart', jsonMarkerDragStartEvent);
      await sendPlatformMessage(mapId, 'marker#onDrag', jsonMarkerDragEvent);
      await sendPlatformMessage(
          mapId, 'marker#onDragEnd', jsonMarkerDragEndEvent);

      expect((await markerDragStartStream.next).value.value,
          equals('drag-start-marker'));
      expect((await markerDragStream.next).value.value, equals('drag-marker'));
      expect((await markerDragEndStream.next).value.value,
          equals('drag-end-marker'));
    });
  });
}
