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

require('es6-shim');

var $ = require('../util/jquery');
var defineClass = require('../util/define-class');

var Place = require('../place');
var DestinationInfo = require('./destination-info');
var DestinationMarker = require('./destination-marker');

var describeDestination = require('../describe-destination');

//named destination marker clients
var SEARCH_CLIENT = 'search';

var MapWidget = defineClass({
  publics: {
    getBounds: function() {
      return this.map.getBounds();
    },

    addControls: function(controlPosition, $controls) {
      var controls = this.map.controls[controlPosition];
      $controls.each(function() {
        controls.push(this);
      });
    },

    bindDestinations: function(destinations) {
      if (this.destinations) {
        this.destinations.onAdd.remove(this.handleDestinationAdd);
        this.destinations.onRemove.remove(this.handleDestinationRemove);
      }

      this.destinations = destinations;

      if (destinations) {
        destinations.onAdd.add(this.handleDestinationAdd);
        destinations.onRemove.add(this.handleDestinationRemove);
      }
    },

    getSelectedDestination: function() {
      return this.selectedDestination;
    },

    clearSearchMarkers: function() {
      $.each(this.searchMarkers, function() {
        this.removeClient(SEARCH_CLIENT);
      });
      this.searchMarkers = [];
    },

    closeActiveInfoWindow: function() {
      if (this.info) {
        this.info.close();
      }
    },

    deselectDestination: function() {
      if (this.selectedDestination) {
        this.selectedDestination.deselect();
      }
    },

    fitAll: function() {
      var geoms = [];

      function addToGeoms() {
        geoms.push({ location: this });
      }

      this.destinations.each(function() {
        if (this.hasPlace()) {
          if (this.leg && this.leg.sync) {
            $.each(this.leg.sync.routes[0]['overview_path'], addToGeoms);
          }
          geoms.push(this.getPlace().getGeometry());
        }
      });

      this.ensureGeomsVisible(geoms);
    },

    fitBounds: function(bounds) {
      this.map.fitBounds(bounds);
    },

    ensureVisible: function(place) {
      this.ensureGeomsVisible([place.getGeometry()]);
    },

    invalidateSize: function() {
      this.maps.event.trigger(this.map, 'resize');
    },

    /**
     * @return whether or not location selection is now enabled. Location
     *  selection can only be enabled when a destination slot has been selected.
     */
    enableLocationSelection: function() {
      if (this.selectedDestination) {
        this.map.setOptions({ draggableCursor: 'auto' });
        this.locationSelectionEnabled = true;
        return true;
      }
      return false;
    },

    disableLocationSelection: function() {
      this.map.setOptions({ draggableCursor: null });
      this.locationSelectionEnabled = false;
    },

    createPlacesService: function() {
      return new this.maps.places.PlacesService(this.map);
    },

    showSearchResults: function(results) {
      var self = this;

      this.clearSearchMarkers();
      this.closeActiveInfoWindow();

      this.fitGeoms(results.map(function(result) {
        return result.geometry;
      }));

      var dest = this.selectedDestination;
      if (results.length === 1 && dest) {
        /* It would be nice if we could distinguish between an autocomplete
         * click and a normal search so that we don't overwrite the search box
         * text for the autocomplete click.*/
        dest.setPlace(new Place(results[0]));
      } else if (results.length > 0) {
        $.each(results, function(i, result) {
          var place = new Place(result);

          var marker = self.getOrCreateMarker(place, SEARCH_CLIENT,
            DestinationMarker.color.RED, null, false);
          self.searchMarkers.push(marker);

          marker.onClick.add(marker.restrictListenerToClient(function() {
            var dest = self.selectedDestination;
            if (dest) {
              dest.setPlace(place);
            }
          }));

          marker.deprioritizeClient();
        });
      }
    }
  },

  privates: {
    handleDestinationAdd: function(destination) {
      var self = this;

      this.destMeta.set(destination, {});

      destination.onPlaceChange.add(function(place) {
        self.handleDestinationPlaceChange(destination, place);
      });
      destination.onDeselect.add(function() {
        self.handleDestinationDeselect(destination);
      });
      destination.onSelect.add(function() {
        self.handleDestinationSelect(destination);
      });

      if (destination.hasNext()) {
        this.updateLeg(destination.getNext());
      }

      return destination;
    },

    handleDestinationRemove: function(destination) {
      var meta = this.destMeta.get(destination);

      if (meta.unbindMarker) {
        meta.unbindMarker();
      }

      if (meta.leg) {
        meta.leg.clear();
      }

      var next = this.destinations.get(destination.getIndex());
      if (next) {
        this.updateLeg(next);
      }

      destination.deselect();

      this.destMeta.delete(destination);
    },

    getOrCreateMarker: function(place, client, color, mergePredicate, update) {
      var self = this;

      var key = place.toKey();

      var marker = this.markers[key];
      if (marker) {
        if (!mergePredicate || mergePredicate(marker)) {
          marker.pushClient(client, color, update);
        } else {
          marker = null;
        }
      } else {
        marker = new DestinationMarker(this.maps, this.map, place,
          client, color);

        if (place.hasDetails()) {
          marker.onClick.add(function() {
            self.showDestinationInfo(marker);
          }, true);
        }

        this.markers[key] = marker;
        marker.onClear.add(function() {
          delete self.markers[key];
        });
      }

      return marker;
    },

    bindDestinationMarker: function(destination) {
      var self = this;

      var place = destination.getPlace();

      var marker = this.getOrCreateMarker(place, destination,
        this.getAppropriateDestinationMarkerColor(destination),
        function(marker) {
          return !marker.hasClient(destination);
        });

      if (!marker) {
        return;
      }

      marker.onClick.add(destination.select);
      function handleSelection() {
        marker.setColor(self.getAppropriateDestinationMarkerColor(destination));
      }
      destination.onSelect.add(handleSelection);
      destination.onDeselect.add(handleSelection);

      function handleOrdinalChange() {
        describeDestination.decorateMarker(marker, destination);
      }

      destination.onOrdinalChange.add(handleOrdinalChange);
      handleOrdinalChange();

      var meta = this.destMeta.get(destination);

      function unbind() {
        marker.removeClient(destination);
        marker.onClick.remove(destination.select);
        destination.onSelect.remove(handleSelection);
        destination.onDeselect.remove(handleSelection);
        destination.onOrdinalChange.remove(handleOrdinalChange);
        destination.onPlaceChange.remove(handlePlaceChange);
        if (meta.unbindMarker === unbind) {
          delete meta.unbindMarker;
        }
      }

      meta.unbindMarker = unbind;

      function handlePlaceChange(newPlace) {
        if ((place && place.toKey()) !== (newPlace && newPlace.toKey())) {
          unbind();
        }
      }

      destination.onPlaceChange.add(handlePlaceChange);
    },

    getAppropriateDestinationMarkerColor: function(destination) {
      return destination.isSelected()?
        DestinationMarker.color.GREEN : DestinationMarker.color.BLUE;
    },

    showDestinationInfo: function(destinationMarker) {
      if (!this.info) {
        this.info = new DestinationInfo(
          this.maps, this.map, destinationMarker.place);
      } else {
        this.info.setPlace(destinationMarker.place);
      }

      this.info.show(destinationMarker.marker);
    },

    handleDestinationPlaceChange: function(destination, place) {
      if (place) {
        this.bindDestinationMarker(destination);
      }

      if (destination.getPrevious()) {
        this.updateLeg(destination);
      }
      if (destination.getNext()) {
        this.updateLeg(destination.getNext());
      }
    },

    handleDestinationDeselect: function(destination) {
      this.selectedDestination = null;
      destination.onPlaceChange.remove(
        this.handleSelectedDestinationPlaceChange);
      this.disableLocationSelection();
    },

    handleDestinationSelect: function(destination) {
      this.deselectDestination();

      this.selectedDestination = destination;
      destination.onPlaceChange.add(this.handleSelectedDestinationPlaceChange);
      this.handleSelectedDestinationPlaceChange(destination.getPlace());
    },

    handleSelectedDestinationPlaceChange: function(place) {
      if (place) {
        this.disableLocationSelection();
        this.ensureVisible(place);
      } else {
        this.enableLocationSelection();
      }
    },

    updateLeg: function(destination) {
      var self = this;
      var maps = this.maps;
      var map = this.map;

      var a = destination.getPrevious().getPlace();
      var b = destination.getPlace();

      var meta = this.destMeta.get(destination);

      var leg = meta.leg;
      if (leg) {
        if (leg.async) {
          leg.async.reject();
        }
        leg.clear();
      } else {
        var renderer = new maps.DirectionsRenderer({
          preserveViewport: true,
          suppressMarkers: true
        });
        meta.leg = leg = {
          renderer: renderer,
          clear: function() {
            // setMap(null) seems to be the best way to clear the nav route
            renderer.setMap(null);
          }
        };
      }

      if (a && b) {
        var request = {
          origin: a.getLocation(),
          destination: b.getLocation(),
          travelMode: maps.TravelMode.DRIVING // TODO(rosswang): user choice
        };

        leg.async = $.Deferred();

        this.directionsService.route(request, function(result, status) {
          if (status === maps.DirectionsStatus.OK) {
            leg.async.resolve(result);
            leg.sync = result;
          } else {
            self.onError({ directionsStatus: status });
            leg.async.reject(status);
          }
        });

        leg.async.done(function(result) {
          leg.renderer.setDirections(result);
          leg.renderer.setMap(map);
        });
      }
    },

    centerOnCurrentLocation: function(navigator) {
      var self = this;
      var maps = this.maps;
      var map = this.map;

      // https://developers.google.com/maps/documentation/javascript/examples/map-geolocation
      if (navigator && navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
          var latLng = new maps.LatLng(
            position.coords.latitude, position.coords.longitude);
          map.setCenter(latLng);

          self.geocoder.geocode({ location: latLng },
            function(results, status) {
              var origin = self.destinations.get(0);
              if (status === maps.GeocoderStatus.OK &&
                  origin && !origin.hasPlace()) {
                origin.setPlace(new Place(results[0]));
              }
            });
          });
      }
    },

    ensureGeomsVisible: function(geoms) {
      var curBounds = this.map.getBounds();
      if (!geoms.every(function(geom) {
            return curBounds.contains(geom.location);
          })) {
        this.fitGeoms(geoms);
      }
    },

    fitGeoms: function(geoms) {
      var curBounds = this.map.getBounds();
      var curSize = curBounds.toSpan();
      function wontShrink(proposed) {
        var size = proposed.toSpan();
        return size.lat() >= curSize.lat() || size.lng() >= curSize.lng();
      }

      if (geoms.length === 1) {
        var geom = geoms[0];
        if (geom.viewport && wontShrink(geom.viewport)) {
          this.map.fitBounds(geom.viewport);
        } else {
          this.map.panTo(geom.location);
        }

      } else if (geoms.length > 1) {
        this.map.fitBounds(geoms.reduce(function(acc, geom) {
          if (geom.viewport) {
            acc.union(geom.viewport);
          } else {
            acc.extend(geom.location);
          }
          return acc;
        }, new this.maps.LatLngBounds()));
      }
    },

    selectLocation: function(latLng) {
      var self = this;
      var maps = this.maps;

      var dest = this.selectedDestination;
      if (dest) {
        if (this.locationSelectionEnabled) {
          self.geocoder.geocode({ location: latLng },
            function(results, status) {
              if (status === maps.GeocoderStatus.OK) {
                dest.setPlace(new Place(results[0]));

                /* If we've just picked a location like this, we probably don't
                 * care about search results anymore. */
                self.clearSearchMarkers();
              }
            });
        } else {
          dest.deselect();
          this.closeActiveInfoWindow();
        }
      }
    }
  },

  constants: ['$', 'maps'],
  events: {
    /**
     * @param bounds
     */
    onBoundsChange: '',

    /**
     * @param error A union with one of the following keys:
     *  directionsStatus
     */
    onError: 'memory'
  },

  // https://developers.google.com/maps/documentation/javascript/tutorial
  init: function(opts) {
    opts = opts || {};
    var self = this;

    var maps = opts.maps || global.google.maps;
    var navigator = opts.navigator || global.navigator;

    this.maps = maps;
    this.navigator = opts.navigator || global.navigator;
    this.geocoder = opts.geocoder || new maps.Geocoder();
    this.directionsService = new maps.DirectionsService();

    this.$ = $('<div>').addClass('map-canvas');

    this.searchMarkers = [];
    this.markers = {};
    this.destMeta = new Map();

    this.initialConfig = {
      center: new maps.LatLng(37.4184, -122.0880), //Googleplex
      zoom: 11
    };

    var map = new maps.Map(this.$[0], this.initialConfig);
    this.map = map;

    maps.event.addListener(map, 'click', function(e) {
      self.selectLocation(e.latLng);
    });
    maps.event.addListener(map, 'bounds_changed', function() {
      self.onBoundsChange(map.getBounds());
    });

    this.centerOnCurrentLocation(navigator);
  }
});

module.exports = MapWidget;
