// 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.

part of google_maps_flutter_web;

/// Type used when passing an override to the _createMap function.
@visibleForTesting
typedef DebugCreateMapFunction = gmaps.GMap Function(
    HtmlElement div, gmaps.MapOptions options);

/// Encapsulates a [gmaps.GMap], its events, and where in the DOM it's rendered.
class GoogleMapController {
  // The internal ID of the map. Used to broadcast events, DOM IDs and everything where a unique ID is needed.
  final int _mapId;

  final CameraPosition _initialCameraPosition;
  final Set<Marker> _markers;
  final Set<Polygon> _polygons;
  final Set<Polyline> _polylines;
  final Set<Circle> _circles;
  // The raw options passed by the user, before converting to gmaps.
  // Caching this allows us to re-create the map faithfully when needed.
  Map<String, dynamic> _rawMapOptions = <String, dynamic>{};

  // Creates the 'viewType' for the _widget
  String _getViewType(int mapId) => 'plugins.flutter.io/google_maps_$mapId';

  // The Flutter widget that contains the rendered Map.
  HtmlElementView? _widget;
  late HtmlElement _div;

  /// The Flutter widget that will contain the rendered Map. Used for caching.
  Widget? get widget {
    if (_widget == null && !_streamController.isClosed) {
      _widget = HtmlElementView(
        viewType: _getViewType(_mapId),
      );
    }
    return _widget;
  }

  // The currently-enabled traffic layer.
  gmaps.TrafficLayer? _trafficLayer;

  /// A getter for the current traffic layer. Only for tests.
  @visibleForTesting
  gmaps.TrafficLayer? get trafficLayer => _trafficLayer;

  // The underlying GMap instance. This is the interface with the JS SDK.
  gmaps.GMap? _googleMap;

  // The StreamController used by this controller and the geometry ones.
  final StreamController<MapEvent> _streamController;

  /// The Stream over which this controller broadcasts events.
  Stream<MapEvent> get events => _streamController.stream;

  // Geometry controllers, for different features of the map.
  CirclesController? _circlesController;
  PolygonsController? _polygonsController;
  PolylinesController? _polylinesController;
  MarkersController? _markersController;
  // Keeps track if _attachGeometryControllers has been called or not.
  bool _controllersBoundToMap = false;

  // Keeps track if the map is moving or not.
  bool _mapIsMoving = false;

  /// Initializes the GMap, and the sub-controllers related to it. Wires events.
  GoogleMapController({
    required int mapId,
    required StreamController<MapEvent> streamController,
    required CameraPosition initialCameraPosition,
    Set<Marker> markers = const <Marker>{},
    Set<Polygon> polygons = const <Polygon>{},
    Set<Polyline> polylines = const <Polyline>{},
    Set<Circle> circles = const <Circle>{},
    Set<TileOverlay> tileOverlays = const <TileOverlay>{},
    Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers =
        const <Factory<OneSequenceGestureRecognizer>>{},
    Map<String, dynamic> mapOptions = const <String, dynamic>{},
  })  : _mapId = mapId,
        _streamController = streamController,
        _initialCameraPosition = initialCameraPosition,
        _markers = markers,
        _polygons = polygons,
        _polylines = polylines,
        _circles = circles,
        _rawMapOptions = mapOptions {
    _circlesController = CirclesController(stream: this._streamController);
    _polygonsController = PolygonsController(stream: this._streamController);
    _polylinesController = PolylinesController(stream: this._streamController);
    _markersController = MarkersController(stream: this._streamController);

    // Register the view factory that will hold the `_div` that holds the map in the DOM.
    // The `_div` needs to be created outside of the ViewFactory (and cached!) so we can
    // use it to create the [gmaps.GMap] in the `init()` method of this class.
    _div = DivElement()
      ..id = _getViewType(mapId)
      ..style.width = '100%'
      ..style.height = '100%';

    ui.platformViewRegistry.registerViewFactory(
      _getViewType(mapId),
      (int viewId) => _div,
    );
  }

  /// Overrides certain properties to install mocks defined during testing.
  @visibleForTesting
  void debugSetOverrides({
    DebugCreateMapFunction? createMap,
    MarkersController? markers,
    CirclesController? circles,
    PolygonsController? polygons,
    PolylinesController? polylines,
  }) {
    _overrideCreateMap = createMap;
    _markersController = markers ?? _markersController;
    _circlesController = circles ?? _circlesController;
    _polygonsController = polygons ?? _polygonsController;
    _polylinesController = polylines ?? _polylinesController;
  }

  DebugCreateMapFunction? _overrideCreateMap;

  gmaps.GMap _createMap(HtmlElement div, gmaps.MapOptions options) {
    if (_overrideCreateMap != null) {
      return _overrideCreateMap!(div, options);
    }
    return gmaps.GMap(div, options);
  }

  /// Initializes the [gmaps.GMap] instance from the stored `rawOptions`.
  ///
  /// This method actually renders the GMap into the cached `_div`. This is
  /// called by the [GoogleMapsPlugin.init] method when appropriate.
  ///
  /// Failure to call this method would result in the GMap not rendering at all,
  /// and most of the public methods on this class no-op'ing.
  void init() {
    var options = _rawOptionsToGmapsOptions(_rawMapOptions);
    // Initial position can only to be set here!
    options = _applyInitialPosition(_initialCameraPosition, options);

    // Create the map...
    final map = _createMap(_div, options);
    _googleMap = map;

    _attachMapEvents(map);
    _attachGeometryControllers(map);

    _renderInitialGeometry(
      markers: _markers,
      circles: _circles,
      polygons: _polygons,
      polylines: _polylines,
    );

    _setTrafficLayer(map, _isTrafficLayerEnabled(_rawMapOptions));
  }

  // Funnels map gmap events into the plugin's stream controller.
  void _attachMapEvents(gmaps.GMap map) {
    map.onClick.listen((event) {
      assert(event.latLng != null);
      _streamController.add(
        MapTapEvent(_mapId, _gmLatLngToLatLng(event.latLng!)),
      );
    });
    map.onRightclick.listen((event) {
      assert(event.latLng != null);
      _streamController.add(
        MapLongPressEvent(_mapId, _gmLatLngToLatLng(event.latLng!)),
      );
    });
    map.onBoundsChanged.listen((event) {
      if (!_mapIsMoving) {
        _mapIsMoving = true;
        _streamController.add(CameraMoveStartedEvent(_mapId));
      }
      _streamController.add(
        CameraMoveEvent(_mapId, _gmViewportToCameraPosition(map)),
      );
    });
    map.onIdle.listen((event) {
      _mapIsMoving = false;
      _streamController.add(CameraIdleEvent(_mapId));
    });
  }

  // Binds the Geometry controllers to a map instance
  void _attachGeometryControllers(gmaps.GMap map) {
    // Now we can add the initial geometry.
    // And bind the (ready) map instance to the other geometry controllers.
    //
    // These controllers are either created in the constructor of this class, or
    // overriden (for testing) by the [debugSetOverrides] method. They can't be
    // null.
    assert(_circlesController != null,
        'Cannot attach a map to a null CirclesController instance.');
    assert(_polygonsController != null,
        'Cannot attach a map to a null PolygonsController instance.');
    assert(_polylinesController != null,
        'Cannot attach a map to a null PolylinesController instance.');
    assert(_markersController != null,
        'Cannot attach a map to a null MarkersController instance.');

    _circlesController!.bindToMap(_mapId, map);
    _polygonsController!.bindToMap(_mapId, map);
    _polylinesController!.bindToMap(_mapId, map);
    _markersController!.bindToMap(_mapId, map);

    _controllersBoundToMap = true;
  }

  // Renders the initial sets of geometry.
  void _renderInitialGeometry({
    Set<Marker> markers = const {},
    Set<Circle> circles = const {},
    Set<Polygon> polygons = const {},
    Set<Polyline> polylines = const {},
  }) {
    assert(
        _controllersBoundToMap,
        'Geometry controllers must be bound to a map before any geometry can ' +
            'be added to them. Ensure _attachGeometryControllers is called first.');

    // The above assert will only succeed if the controllers have been bound to a map
    // in the [_attachGeometryControllers] method, which ensures that all these
    // controllers below are *not* null.

    _markersController!.addMarkers(markers);
    _circlesController!.addCircles(circles);
    _polygonsController!.addPolygons(polygons);
    _polylinesController!.addPolylines(polylines);
  }

  // Merges new options coming from the plugin into the _rawMapOptions map.
  //
  // Returns the updated _rawMapOptions object.
  Map<String, dynamic> _mergeRawOptions(Map<String, dynamic> newOptions) {
    _rawMapOptions = <String, dynamic>{
      ..._rawMapOptions,
      ...newOptions,
    };
    return _rawMapOptions;
  }

  /// Updates the map options from a `Map<String, dynamic>`.
  ///
  /// This method converts the map into the proper [gmaps.MapOptions]
  void updateRawOptions(Map<String, dynamic> optionsUpdate) {
    assert(_googleMap != null, 'Cannot update options on a null map.');

    final newOptions = _mergeRawOptions(optionsUpdate);

    _setOptions(_rawOptionsToGmapsOptions(newOptions));
    _setTrafficLayer(_googleMap!, _isTrafficLayerEnabled(newOptions));
  }

  // Sets new [gmaps.MapOptions] on the wrapped map.
  void _setOptions(gmaps.MapOptions options) {
    _googleMap?.options = options;
  }

  // Attaches/detaches a Traffic Layer on the passed `map` if `attach` is true/false.
  void _setTrafficLayer(gmaps.GMap map, bool attach) {
    if (attach && _trafficLayer == null) {
      _trafficLayer = gmaps.TrafficLayer()..set('map', map);
    }
    if (!attach && _trafficLayer != null) {
      _trafficLayer!.set('map', null);
      _trafficLayer = null;
    }
  }

  // _googleMap manipulation
  // Viewport

  /// Returns the [LatLngBounds] of the current viewport.
  Future<LatLngBounds> getVisibleRegion() async {
    assert(_googleMap != null, 'Cannot get the visible region of a null map.');

    return _gmLatLngBoundsTolatLngBounds(
      await _googleMap!.bounds ?? _nullGmapsLatLngBounds,
    );
  }

  /// Returns the [ScreenCoordinate] for a given viewport [LatLng].
  Future<ScreenCoordinate> getScreenCoordinate(LatLng latLng) async {
    assert(_googleMap != null,
        'Cannot get the screen coordinates with a null map.');
    assert(_googleMap!.projection != null,
        'Cannot compute screen coordinate with a null map or projection.');

    final point =
        _googleMap!.projection!.fromLatLngToPoint!(_latLngToGmLatLng(latLng))!;

    assert(point.x != null && point.y != null,
        'The x and y of a ScreenCoordinate cannot be null.');

    return ScreenCoordinate(x: point.x!.toInt(), y: point.y!.toInt());
  }

  /// Returns the [LatLng] for a `screenCoordinate` (in pixels) of the viewport.
  Future<LatLng> getLatLng(ScreenCoordinate screenCoordinate) async {
    assert(_googleMap != null,
        'Cannot get the lat, lng of a screen coordinate with a null map.');

    final gmaps.LatLng latLng =
        _pixelToLatLng(_googleMap!, screenCoordinate.x, screenCoordinate.y);
    return _gmLatLngToLatLng(latLng);
  }

  /// Applies a `cameraUpdate` to the current viewport.
  Future<void> moveCamera(CameraUpdate cameraUpdate) async {
    assert(_googleMap != null, 'Cannot update the camera of a null map.');

    return _applyCameraUpdate(_googleMap!, cameraUpdate);
  }

  /// Returns the zoom level of the current viewport.
  Future<double> getZoomLevel() async {
    assert(_googleMap != null, 'Cannot get zoom level of a null map.');
    assert(_googleMap!.zoom != null,
        'Zoom level should not be null. Is the map correctly initialized?');

    return _googleMap!.zoom!.toDouble();
  }

  // Geometry manipulation

  /// Applies [CircleUpdates] to the currently managed circles.
  void updateCircles(CircleUpdates updates) {
    assert(
        _circlesController != null, 'Cannot update circles after dispose().');
    _circlesController?.addCircles(updates.circlesToAdd);
    _circlesController?.changeCircles(updates.circlesToChange);
    _circlesController?.removeCircles(updates.circleIdsToRemove);
  }

  /// Applies [PolygonUpdates] to the currently managed polygons.
  void updatePolygons(PolygonUpdates updates) {
    assert(
        _polygonsController != null, 'Cannot update polygons after dispose().');
    _polygonsController?.addPolygons(updates.polygonsToAdd);
    _polygonsController?.changePolygons(updates.polygonsToChange);
    _polygonsController?.removePolygons(updates.polygonIdsToRemove);
  }

  /// Applies [PolylineUpdates] to the currently managed lines.
  void updatePolylines(PolylineUpdates updates) {
    assert(_polylinesController != null,
        'Cannot update polylines after dispose().');
    _polylinesController?.addPolylines(updates.polylinesToAdd);
    _polylinesController?.changePolylines(updates.polylinesToChange);
    _polylinesController?.removePolylines(updates.polylineIdsToRemove);
  }

  /// Applies [MarkerUpdates] to the currently managed markers.
  void updateMarkers(MarkerUpdates updates) {
    assert(
        _markersController != null, 'Cannot update markers after dispose().');
    _markersController?.addMarkers(updates.markersToAdd);
    _markersController?.changeMarkers(updates.markersToChange);
    _markersController?.removeMarkers(updates.markerIdsToRemove);
  }

  /// Shows the [InfoWindow] of the marker identified by its [MarkerId].
  void showInfoWindow(MarkerId markerId) {
    assert(_markersController != null,
        'Cannot show infowindow of marker [${markerId.value}] after dispose().');
    _markersController?.showMarkerInfoWindow(markerId);
  }

  /// Hides the [InfoWindow] of the marker identified by its [MarkerId].
  void hideInfoWindow(MarkerId markerId) {
    assert(_markersController != null,
        'Cannot hide infowindow of marker [${markerId.value}] after dispose().');
    _markersController?.hideMarkerInfoWindow(markerId);
  }

  /// Returns true if the [InfoWindow] of the marker identified by [MarkerId] is shown.
  bool isInfoWindowShown(MarkerId markerId) {
    return _markersController?.isInfoWindowShown(markerId) ?? false;
  }

  // Cleanup

  /// Disposes of this controller and its resources.
  ///
  /// You won't be able to call many of the methods on this controller after
  /// calling `dispose`!
  void dispose() {
    _widget = null;
    _googleMap = null;
    _circlesController = null;
    _polygonsController = null;
    _polylinesController = null;
    _markersController = null;
    _streamController.close();
  }
}
