/**
 * @file
 * Common marker highlighting routines.
 */

/**
 * Highlights marker on rollover.
 * Removes highlight on previous marker.
 *
 * Creates a "circle" at the given point
 * Circle is global variable as there is only one highlighted marker at a time
 * and we want to remove the previously placed polygon before placing a new one.
 *
 * Original code "Google Maps JavaScript API Example"
 * JN201304:
 *    converted rpolygons to circles (not using the shapes.js API, should we be?)
 *    move marker highlight events to custom handler here, to handle radius in pixels (note behavior.radiusInMeters to skip geodesic calcs)
 *    removed google.events and moved events to gmaps binds
 *    added overlay object for creating a shape based on pixels instead of meters (seems to be the use case?)
 *    added gmaps binds for marker higlights, and general highlights.
 *
 * You can add highlights to a map with:
 *    obj.change('addHighlight',-1, {latitude:#, longitude:#} );
 * You can highlight a marker with:
 *    obj.change('markerHighlight',-1, marker);
 *      marker: that marker object used when creating the marker.  It can have options set at marker.highlight
 *
 * A Highlight object has to have either a <LatLng>Position or a <Number>latitude and <Number>longitude
 * Note the new highlight options = {
 *       radius: 10, // radius in pixels
 *       color: '#777777',
 *       weight: 2,
 *       opacity: 0.7,
 *       behavior: {
 *          draggable: false,
 *          editable: false,
 *       }
 *       opts: { actual google.maps.Circle opts can be put here for super custom cases }
 * }
 */

Drupal.gmap.factory.highlight = function(options) {
  return new google.maps.Circle(options);
}

Drupal.gmap.addHandler('gmap', function (elem) {
  var obj = this;
  obj.highlights = {};

  var overlayHandler = function(map, highlight) {
    this.setMap(map);
    this.highlight = highlight;
  }
  overlayHandler.prototype = new google.maps.OverlayView();
  overlayHandler.prototype.onAdd = function() {
    var highlight = this.highlight;
    if ( !highlight.opts ) { highlight.opts = {}; } // sanity
    if ( !highlight.behavior ) { highlight.behavior = {}; } // sanity
    if ( !highlight.position ) { highlight.position = new google.maps.LatLng( highlight.latitude, highlight.longitude ); } // if you have a pos already then use it, otherwise gimme a lat/lon

    $.each({ // collect the options from either the highligh.opts object, from the passed target value, as a behavior or a default value
        radius: {target:'radius',default:10}, // radius in pixels
        strokeColor: {target:'border',default:'#777777'},
        strokeWeight: {target:'weight',default:2},
        strokeOpacity: {target:'opacity',default:0.7},
        fillColor: {target:'color',default:'#777777'},
        fillOpacity: {target:'opacity',default:0.7},
        draggable: {behavior:'draggable',default:false},
        editable: {behavior:'editable',default:false},
      }, function( key , config ) {
        if ( highlight.opts[key] ) { // options was passed in
          return true;
        }
        else if (config.target && highlight[ config.target ]) { // highight.target should have a value
          highlight.opts[key] = highlight[ config.target ];
        }
        else if ( config.behavior && highlight.behavior && highlight.behavior[ config.behavior ] ) { // value is a behaviour
          highlight.opts[key] = highlight.behavior[ config.behavior ];
        }
        else if (config.default) { // default valuee
          highlight.opts[key] = config.default;
        }
      });

    highlight.opts.map = this.map;
    highlight.opts.center = highlight.position;

  }
  overlayHandler.prototype.draw = function() {
    var highlight = this.highlight;
    if ( !this.highlight.behavior.radiusInMeters ) {
      var projection = this.getProjection();
      var mapZoom = this.map.getZoom();
      var center = projection.fromLatLngToDivPixel(highlight.opts.center, mapZoom);
      var radius = highlight.opts.radius;
      var radial = projection.fromDivPixelToLatLng(new google.maps.Point(center.x, center.y+radius), mapZoom); // find a point that is the radius distance away in pixels
      highlight.opts.radius = google.maps.geometry.spherical.computeDistanceBetween (highlight.opts.center, radial);
      highlight.behavior.radiusInMeters = true;
    }
    highlight.highlight = Drupal.gmap.factory.highlight(highlight.opts);
  }
  overlayHandler.prototype.onRemove = function() {
    if ( this.highlight.highlight ) {
      this.highlight.highlight.setMap( null );
    }
  }

  Drupal.gmap.highlight = function (highlight) {
    new overlayHandler(obj.map, highlight); // all actions happen in an overlayview, so that we can input pixels for radius instead of meters and positions
  };
  Drupal.gmap.unhighlight = function( highlight ) { // this can take an object that has a highlight, or a highlight/circle object
    if ( highlight.highlight && highlight.highlight.setMap ) {
      highlight.highlight.setMap( null );
    }
    else if ( highlight.setMap ) {
      highlight.setMap( null );
    }
  }

  // set and remove map highlights

  obj.bind('addHighlight', function(highlight) {
    Drupal.gmap.highlight( highlight );
  });
  obj.bind('removeHighlight', function(highlight) {
    Drupal.gmap.unhighlight( highlight );
  });

 // Marker specific code:
  var activeMarker; // remember that last marker activated.  In the default case we only allow one highlighted marker at a time
  obj.bind('markerHighlight', function (marker) {
    if ( activeMarker && !obj.vars.behavior.allowMultipleMarkerHighlight ) { obj.change('markerUnHighlight',-1, activeMarker); } // deactivate the active marker

    // If the highlight arg option is used in views highlight the marker.
    if ( !marker.highlight ) { marker.highlight = {} }
    if ( !marker.highlight.color && obj.vars.styles.highlight_color ) { marker.highlight.color = '#' + obj.vars.styles.highlight_color; }
    marker.highlight.position = marker.marker.getPosition();
    Drupal.gmap.highlight( marker.highlight );
    activeMarker = marker;
  });
  obj.bind('markerUnHighlight', function(marker) {
    if ( !marker ) { marker = activeMarker; } // remove the active marker if no marker is passed in
    if ( activeMarker === marker ) { activeMarker = null; }
    if ( marker.highlight ) {
      Drupal.gmap.unhighlight(marker.highlight);
    }
  });

  /**
   * Marker Binds
   *
   * Marker highlight code has been moved to this file from the marker.js
   *
   * Note that we rely on the obj.vars.behavior.highlight var to
   * decide if should highlight markers on events.
   * This decision could be made as an outer if conditional, instead
   * of repeated inside each bind, but this arrangement allows for
   * the behaviour to change, at a small cost.
   */

  obj.bind('addmarker', function (marker) {
    if (obj.vars.behavior.highlight) {
      google.maps.event.addListener(marker.marker, 'mouseover', function () {
        obj.change('markerHighlight',-1,marker);
      });
      google.maps.event.addListener(marker.marker, 'mouseout', function () {
        obj.change('markerUnHighlight',-1,marker);
      });
    }
    // If the highlight arg option is used in views highlight the marker.
    if (marker.opts.highlight == 1) {
      obj.change('markerHighlight',-1,marker);
    }
  });

// Originally I moved mouse highlights to the extra event binds before I realized that there is likely a usecase for highlights without enabling extra events
//   obj.bind('mouseovermarker', function(marker) {
//     if (obj.vars.behavior.highlight && marker) {
//       obj.change('markerHighlight',-1,marker);
//     }
//   });
//   obj.bind('mouseoutmarker', function(marker) {
//     if (obj.vars.behavior.highlight && marker) {
//       obj.change('markerUnHighlight',-1,marker);
//     }
//   });

});