// 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:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart';

import 'package:async/async.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, (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(ScreenCoordinate(x: 0, y: 0), mapId: mapId);
      await maps.isMarkerInfoWindowShown(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 jsonMarkerDragStartEvent = <dynamic, dynamic>{
        "mapId": mapId,
        "markerId": "drag-start-marker",
        "position": <double>[1.0, 1.0]
      };
      final jsonMarkerDragEvent = <dynamic, dynamic>{
        "mapId": mapId,
        "markerId": "drag-marker",
        "position": <double>[1.0, 1.0]
      };
      final 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(maps.onMarkerDragStart(mapId: mapId));
      final StreamQueue<MarkerDragEvent> markerDragStream =
          StreamQueue(maps.onMarkerDrag(mapId: mapId));
      final StreamQueue<MarkerDragEndEvent> markerDragEndStream =
          StreamQueue(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"));
    });
  });
}
