// Copyright 2017 The Chromium 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;

final _nullLatLng = LatLng(0, 0);
final _nullLatLngBounds = LatLngBounds(
  northeast: _nullLatLng,
  southwest: _nullLatLng,
);

// Defaults taken from the Google Maps Platform SDK documentation.
final _defaultStrokeColor = Colors.black.value;
final _defaultFillColor = Colors.transparent.value;
final _defaultCssColor = '#000000';
final _defaultCssOpacity = 0.0;

// Indices in the plugin side don't match with the ones
// in the gmaps lib. This translates from plugin -> gmaps.
final _mapTypeToMapTypeId = {
  0: gmaps.MapTypeId.ROADMAP, // "none" in the plugin
  1: gmaps.MapTypeId.ROADMAP,
  2: gmaps.MapTypeId.SATELLITE,
  3: gmaps.MapTypeId.TERRAIN,
  4: gmaps.MapTypeId.HYBRID,
};

// Converts a [Color] into a valid CSS value #RRGGBB.
String _getCssColor(Color color) {
  if (color == null) {
    return _defaultCssColor;
  }
  return '#' + color.value.toRadixString(16).padLeft(8, '0').substring(2);
}

// Extracts the opacity from a [Color].
double _getCssOpacity(Color color) {
  if (color == null) {
    return _defaultCssOpacity;
  }
  return color.opacity;
}

// Converts options from the plugin into gmaps.MapOptions that can be used by the JS SDK.
// The following options are not handled here, for various reasons:
// The following are not available in web, because the map doesn't rotate there:
//   compassEnabled
//   rotateGesturesEnabled
//   tiltGesturesEnabled
// mapToolbarEnabled is unused in web, there's no "map toolbar"
// myLocationButtonEnabled Widget not available in web yet, it needs to be built on top of the maps widget
//   See: https://developers.google.com/maps/documentation/javascript/examples/control-custom
// myLocationEnabled needs to be built through dart:html navigator.geolocation
//   See: https://api.dart.dev/stable/2.8.4/dart-html/Geolocation-class.html
// trafficEnabled is handled when creating the GMap object, since it needs to be added as a layer.
// trackCameraPosition is just a boolan value that indicates if the map has an onCameraMove handler.
// indoorViewEnabled seems to not have an equivalent in web
// buildingsEnabled seems to not have an equivalent in web
// padding seems to behave differently in web than mobile. You can't move UI elements in web.
gmaps.MapOptions _rawOptionsToGmapsOptions(Map<String, dynamic> rawOptions) {
  Map<String, dynamic> optionsUpdate = rawOptions['options'] ?? {};

  gmaps.MapOptions options = gmaps.MapOptions();

  if (_mapTypeToMapTypeId.containsKey(optionsUpdate['mapType'])) {
    options.mapTypeId = _mapTypeToMapTypeId[optionsUpdate['mapType']];
  }

  if (optionsUpdate['minMaxZoomPreference'] != null) {
    options
      ..minZoom = optionsUpdate['minMaxZoomPreference'][0]
      ..maxZoom = optionsUpdate['minMaxZoomPreference'][1];
  }

  if (optionsUpdate['cameraTargetBounds'] != null) {
    // Needs gmaps.MapOptions.restriction and gmaps.MapRestriction
    // see: https://developers.google.com/maps/documentation/javascript/reference/map#MapOptions.restriction
  }

  if (optionsUpdate['zoomControlsEnabled'] != null) {
    options.zoomControl = optionsUpdate['zoomControlsEnabled'];
  }

  if (optionsUpdate['styles'] != null) {
    options.styles = optionsUpdate['styles'];
  }

  if (optionsUpdate['scrollGesturesEnabled'] == false ||
      optionsUpdate['zoomGesturesEnabled'] == false) {
    options.gestureHandling = 'none';
  } else {
    options.gestureHandling = 'auto';
  }

  // These don't have any optionUpdate entry, but they seem to be off in the native maps.
  options.mapTypeControl = false;
  options.fullscreenControl = false;
  options.streetViewControl = false;

  return options;
}

gmaps.MapOptions _applyInitialPosition(
  Map<String, dynamic> rawOptions,
  gmaps.MapOptions options,
) {
  // Adjust the initial position, if passed...
  Map<String, dynamic> initialPosition = rawOptions['initialCameraPosition'];
  if (initialPosition != null) {
    final position = CameraPosition.fromMap(initialPosition);
    options.zoom = position.zoom;
    options.center =
        gmaps.LatLng(position.target.latitude, position.target.longitude);
  }
  return options;
}

// Extracts the status of the traffic layer from the rawOptions map.
bool _isTrafficLayerEnabled(Map<String, dynamic> rawOptions) {
  if (rawOptions['options'] == null) {
    return false;
  }
  return rawOptions['options']['trafficEnabled'] ?? false;
}

// Coverts the incoming JSON object into a List of MapTypeStyler objects.
List<gmaps.MapTypeStyler> _parseStylers(List stylerJsons) {
  return stylerJsons?.map((styler) {
    return gmaps.MapTypeStyler()
      ..color = styler['color']
      ..gamma = styler['gamma']
      ..hue = styler['hue']
      ..invertLightness = styler['invertLightness']
      ..lightness = styler['lightness']
      ..saturation = styler['saturation']
      ..visibility = styler['visibility']
      ..weight = styler['weight'];
  })?.toList();
}

// Converts a String to its corresponding MapTypeStyleElementType enum value.
final _elementTypeToEnum = <String, gmaps.MapTypeStyleElementType>{
  'all': gmaps.MapTypeStyleElementType.ALL,
  'geometry': gmaps.MapTypeStyleElementType.GEOMETRY,
  'geometry.fill': gmaps.MapTypeStyleElementType.GEOMETRY_FILL,
  'geometry.stroke': gmaps.MapTypeStyleElementType.GEOMETRY_STROKE,
  'labels': gmaps.MapTypeStyleElementType.LABELS,
  'labels.icon': gmaps.MapTypeStyleElementType.LABELS_ICON,
  'labels.text': gmaps.MapTypeStyleElementType.LABELS_TEXT,
  'labels.text.fill': gmaps.MapTypeStyleElementType.LABELS_TEXT_FILL,
  'labels.text.stroke': gmaps.MapTypeStyleElementType.LABELS_TEXT_STROKE,
};

// Converts a String to its corresponding MapTypeStyleFeatureType enum value.
final _featureTypeToEnum = <String, gmaps.MapTypeStyleFeatureType>{
  'administrative': gmaps.MapTypeStyleFeatureType.ADMINISTRATIVE,
  'administrative.country':
      gmaps.MapTypeStyleFeatureType.ADMINISTRATIVE_COUNTRY,
  'administrative.land_parcel':
      gmaps.MapTypeStyleFeatureType.ADMINISTRATIVE_LAND_PARCEL,
  'administrative.locality':
      gmaps.MapTypeStyleFeatureType.ADMINISTRATIVE_LOCALITY,
  'administrative.neighborhood':
      gmaps.MapTypeStyleFeatureType.ADMINISTRATIVE_NEIGHBORHOOD,
  'administrative.province':
      gmaps.MapTypeStyleFeatureType.ADMINISTRATIVE_PROVINCE,
  'all': gmaps.MapTypeStyleFeatureType.ALL,
  'landscape': gmaps.MapTypeStyleFeatureType.LANDSCAPE,
  'landscape.man_made': gmaps.MapTypeStyleFeatureType.LANDSCAPE_MAN_MADE,
  'landscape.natural': gmaps.MapTypeStyleFeatureType.LANDSCAPE_NATURAL,
  'landscape.natural.landcover':
      gmaps.MapTypeStyleFeatureType.LANDSCAPE_NATURAL_LANDCOVER,
  'landscape.natural.terrain':
      gmaps.MapTypeStyleFeatureType.LANDSCAPE_NATURAL_TERRAIN,
  'poi': gmaps.MapTypeStyleFeatureType.POI,
  'poi.attraction': gmaps.MapTypeStyleFeatureType.POI_ATTRACTION,
  'poi.business': gmaps.MapTypeStyleFeatureType.POI_BUSINESS,
  'poi.government': gmaps.MapTypeStyleFeatureType.POI_GOVERNMENT,
  'poi.medical': gmaps.MapTypeStyleFeatureType.POI_MEDICAL,
  'poi.park': gmaps.MapTypeStyleFeatureType.POI_PARK,
  'poi.place_of_worship': gmaps.MapTypeStyleFeatureType.POI_PLACE_OF_WORSHIP,
  'poi.school': gmaps.MapTypeStyleFeatureType.POI_SCHOOL,
  'poi.sports_complex': gmaps.MapTypeStyleFeatureType.POI_SPORTS_COMPLEX,
  'road': gmaps.MapTypeStyleFeatureType.ROAD,
  'road.arterial': gmaps.MapTypeStyleFeatureType.ROAD_ARTERIAL,
  'road.highway': gmaps.MapTypeStyleFeatureType.ROAD_HIGHWAY,
  'road.highway.controlled_access':
      gmaps.MapTypeStyleFeatureType.ROAD_HIGHWAY_CONTROLLED_ACCESS,
  'road.local': gmaps.MapTypeStyleFeatureType.ROAD_LOCAL,
  'transit': gmaps.MapTypeStyleFeatureType.TRANSIT,
  'transit.line': gmaps.MapTypeStyleFeatureType.TRANSIT_LINE,
  'transit.station': gmaps.MapTypeStyleFeatureType.TRANSIT_STATION,
  'transit.station.airport':
      gmaps.MapTypeStyleFeatureType.TRANSIT_STATION_AIRPORT,
  'transit.station.bus': gmaps.MapTypeStyleFeatureType.TRANSIT_STATION_BUS,
  'transit.station.rail': gmaps.MapTypeStyleFeatureType.TRANSIT_STATION_RAIL,
  'water': gmaps.MapTypeStyleFeatureType.WATER,
};

// The keys we'd expect to see in a serialized MapTypeStyle JSON object.
final _mapStyleKeys = {
  'elementType',
  'featureType',
  'stylers',
};

// Checks if the passed in Map contains some of the _mapStyleKeys.
bool _isJsonMapStyle(Map value) {
  return _mapStyleKeys.intersection(value.keys.toSet()).isNotEmpty;
}

// Converts an incoming JSON-encoded Style info, into the correct gmaps array.
List<gmaps.MapTypeStyle> _mapStyles(String mapStyleJson) {
  List<gmaps.MapTypeStyle> styles = [];
  if (mapStyleJson != null) {
    styles = json.decode(mapStyleJson, reviver: (key, value) {
      if (value is Map && _isJsonMapStyle(value)) {
        return gmaps.MapTypeStyle()
          ..elementType = _elementTypeToEnum[value['elementType']]
          ..featureType = _featureTypeToEnum[value['featureType']]
          ..stylers = _parseStylers(value['stylers']);
      }
      return value;
    }).cast<gmaps.MapTypeStyle>();
  }
  return styles;
}

gmaps.LatLng _latLngToGmLatLng(LatLng latLng) {
  if (latLng == null) return null;
  return gmaps.LatLng(latLng.latitude, latLng.longitude);
}

LatLng _gmLatLngToLatLng(gmaps.LatLng latLng) {
  if (latLng == null) return _nullLatLng;
  return LatLng(latLng.lat, latLng.lng);
}

LatLngBounds _gmLatLngBoundsTolatLngBounds(gmaps.LatLngBounds latLngBounds) {
  if (latLngBounds == null) {
    return _nullLatLngBounds;
  }

  return LatLngBounds(
    southwest: _gmLatLngToLatLng(latLngBounds.southWest),
    northeast: _gmLatLngToLatLng(latLngBounds.northEast),
  );
}

CameraPosition _gmViewportToCameraPosition(gmaps.GMap map) {
  return CameraPosition(
    target: _gmLatLngToLatLng(map.center),
    bearing: map.heading ?? 0,
    tilt: map.tilt ?? 0,
    zoom: map.zoom?.toDouble() ?? 10,
  );
}

Set<Marker> _rawOptionsToInitialMarkers(Map<String, dynamic> rawOptions) {
  final List<Map<String, dynamic>> list = rawOptions['markersToAdd'];
  Set<Marker> markers = {};
  markers.addAll(list?.map((rawMarker) {
        Offset offset;
        LatLng position;
        InfoWindow infoWindow;
        BitmapDescriptor icon;
        if (rawMarker['anchor'] != null) {
          offset = Offset((rawMarker['anchor'][0]), (rawMarker['anchor'][1]));
        }
        if (rawMarker['position'] != null) {
          position = LatLng.fromJson(rawMarker['position']);
        }
        if (rawMarker['infoWindow'] != null) {
          final String title = rawMarker['infoWindow']['title'];
          final String snippet = rawMarker['infoWindow']['snippet'];
          if (title != null || snippet != null) {
            infoWindow = InfoWindow(
              title: title ?? '',
              snippet: snippet ?? '',
            );
          }
        }
        if (rawMarker['icon'] != null) {
          icon = BitmapDescriptor.fromJson(rawMarker['icon']);
        }
        return Marker(
          markerId: MarkerId(rawMarker['markerId']),
          alpha: rawMarker['alpha'],
          anchor: offset,
          consumeTapEvents: rawMarker['consumeTapEvents'],
          draggable: rawMarker['draggable'],
          flat: rawMarker['flat'],
          icon: icon,
          infoWindow: infoWindow,
          position: position ?? _nullLatLng,
          rotation: rawMarker['rotation'],
          visible: rawMarker['visible'],
          zIndex: rawMarker['zIndex'],
        );
      }) ??
      []);
  return markers;
}

Set<Circle> _rawOptionsToInitialCircles(Map<String, dynamic> rawOptions) {
  final List<Map<String, dynamic>> list = rawOptions['circlesToAdd'];
  Set<Circle> circles = {};
  circles.addAll(list?.map((rawCircle) {
        LatLng center;
        if (rawCircle['center'] != null) {
          center = LatLng.fromJson(rawCircle['center']);
        }
        return Circle(
          circleId: CircleId(rawCircle['circleId']),
          consumeTapEvents: rawCircle['consumeTapEvents'],
          fillColor: Color(rawCircle['fillColor'] ?? _defaultFillColor),
          center: center ?? _nullLatLng,
          radius: rawCircle['radius'],
          strokeColor: Color(rawCircle['strokeColor'] ?? _defaultStrokeColor),
          strokeWidth: rawCircle['strokeWidth'],
          visible: rawCircle['visible'],
          zIndex: rawCircle['zIndex'],
        );
      }) ??
      []);
  return circles;
}

// Unsupported on the web: endCap, jointType, patterns and startCap.
Set<Polyline> _rawOptionsToInitialPolylines(Map<String, dynamic> rawOptions) {
  final List<Map<String, dynamic>> list = rawOptions['polylinesToAdd'];
  Set<Polyline> polylines = {};
  polylines.addAll(list?.map((rawPolyline) {
        return Polyline(
          polylineId: PolylineId(rawPolyline['polylineId']),
          consumeTapEvents: rawPolyline['consumeTapEvents'],
          color: Color(rawPolyline['color'] ?? _defaultStrokeColor),
          geodesic: rawPolyline['geodesic'],
          visible: rawPolyline['visible'],
          zIndex: rawPolyline['zIndex'],
          width: rawPolyline['width'],
          points: rawPolyline['points']
              ?.map<LatLng>((rawPoint) => LatLng.fromJson(rawPoint))
              ?.toList(),
        );
      }) ??
      []);
  return polylines;
}

Set<Polygon> _rawOptionsToInitialPolygons(Map<String, dynamic> rawOptions) {
  final List<Map<String, dynamic>> list = rawOptions['polygonsToAdd'];
  Set<Polygon> polygons = {};

  polygons.addAll(list?.map((rawPolygon) {
        return Polygon(
          polygonId: PolygonId(rawPolygon['polygonId']),
          consumeTapEvents: rawPolygon['consumeTapEvents'],
          fillColor: Color(rawPolygon['fillColor'] ?? _defaultFillColor),
          geodesic: rawPolygon['geodesic'],
          strokeColor: Color(rawPolygon['strokeColor'] ?? _defaultStrokeColor),
          strokeWidth: rawPolygon['strokeWidth'],
          visible: rawPolygon['visible'],
          zIndex: rawPolygon['zIndex'],
          points: rawPolygon['points']
              ?.map<LatLng>((rawPoint) => LatLng.fromJson(rawPoint))
              ?.toList(),
          holes: rawPolygon['holes']
              ?.map<List<LatLng>>((List hole) => hole
                  ?.map<LatLng>((rawPoint) => LatLng.fromJson(rawPoint))
                  ?.toList())
              ?.toList(),
        );
      }) ??
      []);
  return polygons;
}

// Convert plugin objects to gmaps.Options objects
// TODO: Move to their appropriate objects, maybe make these copy constructors:
// Marker.fromMarker(anotherMarker, moreOptions);

gmaps.InfoWindowOptions _infoWindowOptionsFromMarker(Marker marker) {
  if ((marker.infoWindow?.title?.isEmpty ?? true) &&
      (marker.infoWindow?.snippet?.isEmpty ?? true)) {
    return null;
  }

  // Add an outer wrapper to the contents of the infowindow, we need it to listen
  // to click events...
  final HtmlElement container = DivElement()
    ..id = 'gmaps-marker-${marker.markerId.value}-infowindow';
  if (marker.infoWindow.title?.isNotEmpty ?? false) {
    final HtmlElement title = HeadingElement.h3()
      ..className = 'infowindow-title'
      ..innerText = marker.infoWindow.title;
    container.children.add(title);
  }
  if (marker.infoWindow.snippet?.isNotEmpty ?? false) {
    final HtmlElement snippet = DivElement()
      ..className = 'infowindow-snippet'
      ..setInnerHtml(
        sanitizeHtml(marker.infoWindow.snippet),
        treeSanitizer: NodeTreeSanitizer.trusted,
      );
    container.children.add(snippet);
  }

  return gmaps.InfoWindowOptions()
    ..content = container
    ..zIndex = marker.zIndex;
  // TODO: Compute the pixelOffset of the infoWindow, from the size of the Marker,
  // and the marker.infoWindow.anchor property.
}

// Computes the options for a new [gmaps.Marker] from an incoming set of options
// [marker], and the existing marker registered with the map: [currentMarker].
// Preserves the position from the [currentMarker], if set.
gmaps.MarkerOptions _markerOptionsFromMarker(
  Marker marker,
  gmaps.Marker currentMarker,
) {
  final iconConfig = marker.icon?.toJson() as List;
  gmaps.Icon icon;

  if (iconConfig != null) {
    if (iconConfig[0] == 'fromAssetImage') {
      assert(iconConfig.length >= 2);
      // iconConfig[2] contains the DPIs of the screen, but that information is
      // already encoded in the iconConfig[1]

      icon = gmaps.Icon()
        ..url = ui.webOnlyAssetManager.getAssetUrl(iconConfig[1]);

      // iconConfig[3] may contain the [width, height] of the image, if passed!
      if (iconConfig.length >= 4 && iconConfig[3] != null) {
        final size = gmaps.Size(iconConfig[3][0], iconConfig[3][1]);
        icon
          ..size = size
          ..scaledSize = size;
      }
    } else if (iconConfig[0] == 'fromBytes') {
      // Grab the bytes, and put them into a blob
      List<int> bytes = iconConfig[1];
      final blob = Blob([bytes]); // Let the browser figure out the encoding
      icon = gmaps.Icon()..url = Url.createObjectUrlFromBlob(blob);
    }
  }
  return gmaps.MarkerOptions()
    ..position = currentMarker?.position ??
        gmaps.LatLng(
          marker.position.latitude,
          marker.position.longitude,
        )
    ..title = sanitizeHtml(marker.infoWindow?.title ?? "")
    ..zIndex = marker.zIndex
    ..visible = marker.visible
    ..opacity = marker.alpha
    ..draggable = marker.draggable
    ..icon = icon;
  // TODO: Compute anchor properly, otherwise infowindows attach to the wrong spot.
  // Flat and Rotation are not supported directly on the web.
}

gmaps.CircleOptions _circleOptionsFromCircle(Circle circle) {
  final populationOptions = gmaps.CircleOptions()
    ..strokeColor = _getCssColor(circle.strokeColor)
    ..strokeOpacity = _getCssOpacity(circle.strokeColor)
    ..strokeWeight = circle.strokeWidth
    ..fillColor = _getCssColor(circle.fillColor)
    ..fillOpacity = _getCssOpacity(circle.fillColor)
    ..center = gmaps.LatLng(circle.center.latitude, circle.center.longitude)
    ..radius = circle.radius
    ..visible = circle.visible;
  return populationOptions;
}

gmaps.PolygonOptions _polygonOptionsFromPolygon(
    gmaps.GMap googleMap, Polygon polygon) {
  List<gmaps.LatLng> path = [];
  polygon.points.forEach((point) {
    path.add(_latLngToGmLatLng(point));
  });
  final polygonDirection = _isPolygonClockwise(path);
  List<List<gmaps.LatLng>> paths = [path];
  int holeIndex = 0;
  polygon.holes?.forEach((hole) {
    List<gmaps.LatLng> holePath =
        hole.map((point) => _latLngToGmLatLng(point)).toList();
    if (_isPolygonClockwise(holePath) == polygonDirection) {
      holePath = holePath.reversed.toList();
      if (kDebugMode) {
        print(
            'Hole [$holeIndex] in Polygon [${polygon.polygonId.value}] has been reversed.'
            ' Ensure holes in polygons are "wound in the opposite direction to the outer path."'
            ' More info: https://github.com/flutter/flutter/issues/74096');
      }
    }
    paths.add(holePath);
    holeIndex++;
  });
  return gmaps.PolygonOptions()
    ..paths = paths
    ..strokeColor = _getCssColor(polygon.strokeColor)
    ..strokeOpacity = _getCssOpacity(polygon.strokeColor)
    ..strokeWeight = polygon.strokeWidth
    ..fillColor = _getCssColor(polygon.fillColor)
    ..fillOpacity = _getCssOpacity(polygon.fillColor)
    ..visible = polygon.visible
    ..zIndex = polygon.zIndex
    ..geodesic = polygon.geodesic;
}

/// Calculates the direction of a given Polygon
/// based on: https://stackoverflow.com/a/1165943
///
/// returns [true] if clockwise [false] if counterclockwise
bool _isPolygonClockwise(List<gmaps.LatLng> path) {
  var direction = 0.0;
  for (var i = 0; i < path.length; i++) {
    direction = direction +
        ((path[(i + 1) % path.length].lat - path[i].lat) *
            (path[(i + 1) % path.length].lng + path[i].lng));
  }
  return direction >= 0;
}

gmaps.PolylineOptions _polylineOptionsFromPolyline(
    gmaps.GMap googleMap, Polyline polyline) {
  List<gmaps.LatLng> paths = [];
  polyline.points.forEach((point) {
    paths.add(_latLngToGmLatLng(point));
  });

  return gmaps.PolylineOptions()
    ..path = paths
    ..strokeWeight = polyline.width
    ..strokeColor = _getCssColor(polyline.color)
    ..strokeOpacity = _getCssOpacity(polyline.color)
    ..visible = polyline.visible
    ..zIndex = polyline.zIndex
    ..geodesic = polyline.geodesic;
//  this.endCap = Cap.buttCap,
//  this.jointType = JointType.mitered,
//  this.patterns = const <PatternItem>[],
//  this.startCap = Cap.buttCap,
//  this.width = 10,
}

// Translates a [CameraUpdate] into operations on a [gmaps.GMap].
void _applyCameraUpdate(gmaps.GMap map, CameraUpdate update) {
  final json = update.toJson();
  switch (json[0]) {
    case 'newCameraPosition':
      map.heading = json[1]['bearing'];
      map.zoom = json[1]['zoom'];
      map.panTo(gmaps.LatLng(json[1]['target'][0], json[1]['target'][1]));
      map.tilt = json[1]['tilt'];
      break;
    case 'newLatLng':
      map.panTo(gmaps.LatLng(json[1][0], json[1][1]));
      break;
    case 'newLatLngZoom':
      map.zoom = json[2];
      map.panTo(gmaps.LatLng(json[1][0], json[1][1]));
      break;
    case 'newLatLngBounds':
      map.fitBounds(gmaps.LatLngBounds(
          gmaps.LatLng(json[1][0][0], json[1][0][1]),
          gmaps.LatLng(json[1][1][0], json[1][1][1])));
      // padding = json[2];
      // Needs package:google_maps ^4.0.0 to adjust the padding in fitBounds
      break;
    case 'scrollBy':
      map.panBy(json[1], json[2]);
      break;
    case 'zoomBy':
      gmaps.LatLng focusLatLng;
      double zoomDelta = json[1] ?? 0;
      // Web only supports integer changes...
      int newZoomDelta = zoomDelta < 0 ? zoomDelta.floor() : zoomDelta.ceil();
      if (json.length == 3) {
        // With focus
        try {
          focusLatLng = _pixelToLatLng(map, json[2][0], json[2][1]);
        } catch (e) {
          // https://github.com/a14n/dart-google-maps/issues/87
          // print('Error computing new focus LatLng. JS Error: ' + e.toString());
        }
      }
      map.zoom = map.zoom + newZoomDelta;
      if (focusLatLng != null) {
        map.panTo(focusLatLng);
      }
      break;
    case 'zoomIn':
      map.zoom++;
      break;
    case 'zoomOut':
      map.zoom--;
      break;
    case 'zoomTo':
      map.zoom = json[1];
      break;
    default:
      throw UnimplementedError('Unimplemented CameraMove: ${json[0]}.');
  }
}

// original JS by: Byron Singh (https://stackoverflow.com/a/30541162)
gmaps.LatLng _pixelToLatLng(gmaps.GMap map, int x, int y) {
  final ne = map.bounds.northEast;
  final sw = map.bounds.southWest;
  final projection = map.projection;

  final topRight = projection.fromLatLngToPoint(ne);
  final bottomLeft = projection.fromLatLngToPoint(sw);

  final scale = 1 << map.zoom; // 2 ^ zoom

  final point =
      gmaps.Point((x / scale) + bottomLeft.x, (y / scale) + topRight.y);

  return projection.fromPointToLatLng(point);
}
