// This file must be loaded after the google maps API is loaded
var DealerMapBase = Class.create();
DealerMapBase.prototype = {

  drawOnce: false,

  initialize: function() {
    this.defaults = Object.extend({
      mapId: "map",
      controlsOn: true,
      miniIcon: "/maps/images/dloc_marker_pin_blue.png",
      miniIconH: "/maps/images/dloc_marker_pin.png",
      miniIconShadow: "/maps/images/dloc_marker_pin_shadow.png",
      miniIconTransparent: "/maps/images/dloc_marker_pin_trans.png",
      clusterIcon: "/maps/images/cluster.png",
      clusterIconH: "/maps/images/cluster_hover.png",
      clusterShadow: "/maps/images/cluster_shadow.png",
      clusterIconTransparent: "/maps/images/cluster_trans.png",
      serviceURL: "/maps/getDealerClustersC.php",
      msaURL: "/maps/getMSAMap.php",
      windowFromClusterURL: "/maps/explodeCluster.php",
      windowFromClusterURL2: "/maps/getWindowFromCluster.php",
      dealerInfoURL: "/maps/getDealerInfo.php",
      zoomThreshold: 9,
      zoomMakeThresh: 7,
      zoomStart: 4
     }, arguments[0] || {});
    this.preCreate();
    this.createGMap();
    this.buildIcons();
    this.createListeners();
  },

  preCreate: function() {
  },

  createGMap: function() {
    var map = new GMap2($(this.defaults.mapId));

    this.markerInfo = [];//new Object;

    if (this.defaults.controlsOn) {
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
    }

    if (this.defaults.zipcode) {
      this.userZoom = false;
      this.zoomToZip(this.defaults.zipcode);
    } else {
      this.userZoom = false;
      map.setCenter(new GLatLng(37.4419, -95), this.defaults.zoomStart);
    }

    this.map = map;
    this.userZoom = true;

    //Adds a marker manager
    var mgrOptions = { borderPadding: 50, maxZoom: 15, trackMarkers: true };
    map.markerMgr = new MarkerManager(map, mgrOptions);
  },

  buildIcons: function() {
    var miniIcon = new GIcon();
    miniIcon.image = this.defaults.miniIcon;
    miniIcon.shadow = this.defaults.miniIconShadow;
    miniIcon.transparent = this.defaults.miniIconTransparent;
    miniIcon.iconSize = new GSize(17, 21);
    miniIcon.shadowSize = new GSize(28, 22);
    miniIcon.iconAnchor = new GPoint(6, 20);
    miniIcon.infoShadowAnchor = new GPoint(-5, 100);
    miniIcon.infoWindowAnchor = new GPoint(-12, -2);
    this.miniIcon = miniIcon;
    var clusterIcon = new GIcon();
    clusterIcon.image = this.defaults.clusterIcon;
    clusterIcon.shadow = this.defaults.clusterShadow;
    clusterIcon.transparent = this.defaults.clusterIconTransparent;
    clusterIcon.iconSize = new GSize(36,37);
    clusterIcon.shadowSize = new GSize(39, 37);
    clusterIcon.iconAnchor = new GPoint(18,18);
    clusterIcon.infoShadowAnchor = new GPoint(20, 20);
    clusterIcon.infoWindowAnchor = new GPoint(-5,-6);
    this.clusterIcon = clusterIcon;
  },

  createListeners: function() {
    GEvent.addListener(this.map, "dragend", this.mapZoomend.bind(this) );
    GEvent.addListener(this.map, "zoomend", this.mapZoomend.bind(this) );
  },

  //call-back functions

  mapZoomend: function() {
    if (this.userZoom) {
      this.loadByBounds();
    }
    this.userZoom = true;
  },

  showOverlays: function(r) {
   var json = r.responseText.evalJSON();
   
   // remove anything already drawn
   this.clearOverlays();

  if (json.status == "forced_results") {
    // In case of forced_results we reposition the window
    var centerPoint = new GLatLng((json.bounds.n-json.bounds.s)/2 + json.bounds.s,
                  (json.bounds.e-json.bounds.w)/2 + json.bounds.w);
    this.userZoom=false;
    this.dragged=true;
    var zoom = json.bounds.zoom;
    this.map.setCenter(centerPoint, zoom);
  }
   var drawPoint = this.drawPoint.bind(this);
   this.dealer_ids = json.dealer_ids;
   
   if (make_name != '' && model_name != ''){
    var txt = '';
    $('city_list').update(txt);
   }
   json.results.each(drawPoint);
   if (make_name != '' && model_name != ''){
    $('city_list').style.height = '488px';
   }
   this.finishOverlays(json);
  },

  finishOverlays: function(json) {
  },

  clearOverlays: function() {
    this.map.clearOverlays();

    this.drawOnce = true;
  },

  drawPoint: function (details) {
    var lon = parseFloat(details.longitude);
    var lat = parseFloat(details.latitude);

    // not sure which is the correct way to do this
    var point = new GPoint(lon, lat);
    var marker;

    if (details.type=='point') {
      marker = new GMarker(point, {icon: this.miniIcon});
      this.markerInfo[details.cluster_id]={marker: marker, point: point, count: details.count};
      this.pointListeners(details.cluster_id);
    }
    else {
      marker = new GMarker(point, {icon: this.clusterIcon});
      this.markerInfo[details.cluster_id]={marker: marker, count: details.count};
      this.clusterListeners(details.cluster_id);
    }

    this.map.addOverlay(marker);
    //Adds arrows for out of sight markes
    //new MarkerTracker(marker, this.map);
    //Add marker to Manager
    this.map.markerMgr.addMarker(marker, 1);
  },

  pointListeners: function(cluster_id) {
    var marker = this.markerInfo[cluster_id].marker;
    GEvent.addListener(marker, "mouseover", function() { this.getDealerName(marker); }.bind(this));
  },

  clusterListeners: function(cluster_id) {
    var marker = this.markerInfo[cluster_id].marker;
    GEvent.addListener(marker, "click", function() { this.loadByCluster(cluster_id); }.bind(this));
  },

  // Functions called by various events

  loadByCluster: function(clusterid) {
    var x = this.map.getSize().width;
    var y = this.map.getSize().height;
    var zoom = this.map.getZoom();

    var makeValue = this.makeValue();
    var modelValue = this.modelValue();
    var queryOptions = {x: x, y: y, cluster_id: clusterid, 'make[]': makeValue, 'model[]': modelValue};

    if (makeValue !== '' && zoom > this.defaults.zoomMakeThresh) {
      queryOptions.cluster='no';
    }

    var url = zoom <= this.defaults.zoomThreshold ?
      this.defaults.windowFromClusterURL2 :
      this.defaults.windowFromClusterURL;
    new Ajax.Request(url,{method:'get',
      parameters: queryOptions,
      onlyLatestOfClass: url,
      onSuccess: this.showOverlays.bind(this)
		});
  },

  getDealerName: function(marker) {
    new Ajax.Request(this.defaults.dealerInfoURL, {method:'get',
	  parameters: {'make[]': this.makeValue(), cluster_id: marker.clusterid },
	  onSuccess: function(r) {this.showDealerInfo(r,marker)}.bind(this)});
  },

  zoomToZip: function(zip, make, model) {
    this.defaults.forceResults = true;
    var geocoder = new GClientGeocoder();
    geocoder.getLatLng(zip, function(point) {
    if (!point) {
      this.map.setCenter(new GLatLng(37.4419, -95), 8);
      } else {
        this.centerPoint=point;
        this.userZoom=false;
        this.dragged=true;
        this.map.setCenter(point, 10);
        if (typeof(model_name) != 'undefined' && model_name != '')
          this.loadByBounds(make, model);
      }
    }.bind(this));
  },

  zoomToMSA: function() {
    var x = this.map.getSize().width;
    var y = this.map.getSize().height;
    var makeValue = this.makeValue();
    var modelValue = this.modelValue();

    var queryOptions = {x: x, y: y, msa: msa, 'make[]': makeValue, 'model[]': modelValue };

    if (makeValue != '') {
      queryOptions.cluster='no';
    }

    new Ajax.Request(this.defaults.msaURL, {method:'get',
	  parameters: queryOptions, onSuccess: this.showOverlays.bind(this)});
  },

  loadByBounds: function(make, model) {
    if(this.drawOnce){
      return;
    }
    var bounds = this.map.getBounds();
    var southWest = bounds.getSouthWest();
    var northEast = bounds.getNorthEast();
    var zoom = this.map.getZoom();
    var x = this.map.getSize().width;
    var y = this.map.getSize().height;

    var makeValue = make?make:this.makeValue();
    var modelValue = model?model:this.modelValue();

    var queryOptions = { s: southWest.y, w: southWest.x, n: northEast.y, e: northEast.x, zoom: zoom,
			 x: x, y: y, 'make[]': makeValue, 'model[]': modelValue};

    if (this.defaults.forceResults ) {
      queryOptions.forceResults = true; this.defaults.forceResults = false;
    }

    if (makeValue != '' && zoom > this.defaults.zoomMakeThresh) {
      queryOptions.cluster='no'
    }

    new Ajax.Request(this.defaults.serviceURL, {method:'get',
	  parameters: queryOptions,
	  onlyLatestOfClass: 'serviceURL',
	  onSuccess: this.showOverlays.bind(this)});
  },

  makeValue: function() {
    return $F("ajax_make_id");
  },
  modelValue: function(){
    return $F("ajax_model_id");
  }
};

Ajax.currentRequests = {};

Ajax.Responders.register({
  onCreate: function(request) {
    if (request.options.onlyLatestOfClass && Ajax.currentRequests[request.options.onlyLatestOfClass]) {
      // if a request of this class is already in progress, attempt to abort it before launching this new request
      try { Ajax.currentRequests[request.options.onlyLatestOfClass].transport.abort(); } catch(e) {}
    }
    // keep note of this request object so we can cancel it if superceded
    Ajax.currentRequests[request.options.onlyLatestOfClass] = request;
  },
  onComplete: function(request) {
    if (request.options.onlyLatestOfClass) {
      // remove the request from our cache once completed so it can be garbage collected
       Ajax.currentRequests[request.options.onlyLatestOfClass] = null;
    }
  }
});
