// 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 _ambiguate(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'));
    });
  });
}

/// This allows a value of type T or T? to be treated as a value of type T?.
///
/// We use this so that APIs that have become non-nullable can still be used
/// with `!` and `?` on the stable branch.
T? _ambiguate<T>(T? value) => value;
