// required includes: "yui/event/event.js", "yui/connection/connection.js", boundPlane.js, gmaps.js
mapPlaces = {}; // namespace object
mapPlaces.areas = []; // array of Area objects
mapPlaces.spots = []; // array of Spot objects

// data is the json from the server, element is the piece of the dom
mapPlaces.Area = function(data, element) {
  this.data = data;
  this.element = element;

  YAHOO.util.Event.addListener(element, 'mouseover', this.onMouseOver, this, true);
  YAHOO.util.Event.addListener(element, 'mouseout', this.onMouseOut, this, true);
  if (this.onClick) { // may be set by main page
    YAHOO.util.Event.addListener(element, 'click', this.onClick, this, true);
  }
};

mapPlaces.Area.prototype = {
  bounds: null, // of currently displayed rectangle

  removeEvents: function() {
    YAHOO.util.Event.removeListener(this.element, 'mouseover');
    YAHOO.util.Event.removeListener(this.element, 'mouseout');
    if (this.onClick) { // may be set by main page
      YAHOO.util.Event.removeListener(this.element, 'click');
    }
  },

  onMouseOver: function(event) {
    mapPlaces.eraseBox(mapPlaces.Area.bounds);
    mapPlaces.Area.bounds = new BoundPane(this.data.bounds.n, this.data.bounds.s, this.data.bounds.w, this.data.bounds.e);
    mapPlaces.Area.bounds.opacity_ = 1/8;
    mapPlaces.Area.bounds.backgroundColor_ = "#ff2020";
    mapPlaces.drawBox(mapPlaces.Area.bounds);
  },

  onMouseOut: function(event) {
    mapPlaces.eraseBox(mapPlaces.Area.bounds);
  }
}; //Area

mapPlaces.Spot = function(data, element) {
  this.data = data;
  this.element = element;

  YAHOO.util.Event.addListener(element, 'mouseover', this.onMouseOver, this, true);
  YAHOO.util.Event.addListener(element, 'mouseout', this.onMouseOut, this, true);
  if (this.onClick) { // may be set by main page
    YAHOO.util.Event.addListener(element, 'click', this.onClick, this, true);
  }
};

mapPlaces.Spot.prototype = {
  flag: null,

  removeEvents: function() {
    YAHOO.util.Event.removeListener(this.element, 'mouseover');
    YAHOO.util.Event.removeListener(this.element, 'mouseout');
    if (this.onClick) { // may be set by main page
      YAHOO.util.Event.removeListener(this.element, 'click');
    }
  },

  onMouseOver: function(event) {
    this.removeFlag();
    mapPlaces.Spot.flag = new GMarker(new GPoint(this.data.lon, this.data.lat));
    map.addOverlay(mapPlaces.Spot.flag);
  },

  onMouseOut: function(event) {
    this.removeFlag();
  },

  removeFlag: function() {
    if (mapPlaces.Spot.flag) { map.removeOverlay(mapPlaces.Spot.flag); }
  }
}; //Spot

mapPlaces.eraseBox = function(bounds) { if (bounds != null) { map.removeOverlay(bounds); } };

mapPlaces.drawBox = function(bounds) { map.addOverlay(bounds); };

mapPlaces.mapMoveListener = function() {
  var bounds = map.getBounds();
  var n = bounds.getNorthEast().lat();
  var e = bounds.getNorthEast().lng();
  var s = bounds.getSouthWest().lat();
  var w = bounds.getSouthWest().lng();
  var params = "n="+n+"&s="+s+"&e="+e+"&w="+w; //  GLog.write(params);
  var callback = {
    success: mapPlaces.mapMove,
    // ZAT_TODO: handle failures better
    failure: function(response) { alert("mapPlaces.mapMoveListener failed: " + response.status); },

    argument: 0
  }
  YAHOO.util.Connect.asyncRequest('POST', 'lib/ajax/map_move.php', callback, params);
};

mapPlaces.areaElem = function(areaData) {
  var li = document.createElement("li");
  li.innerHTML = mapPlaces.areaAction(areaData);
  return li;
};

mapPlaces.spotElem = function(spotData) {
  var li = document.createElement("li");
  li.innerHTML = mapPlaces.spotAction(spotData);
  return li;
};

// called when the ajax request has returned
mapPlaces.mapMove = function(xhr) {
//  GLog.write(xhr.responseText);
  // remove any event handlers in the old lists and empty the list
  for (var i = 0; i < mapPlaces.areas.length; i++) {
    mapPlaces.areas[i].removeEvents();
  }
  mapPlaces.areas = [];
  for (var i = 0; i < mapPlaces.spots.length; i++) {
    mapPlaces.spots[i].removeEvents();
  }
  mapPlaces.spots = [];
  // remove old list from the dom tree and create new empty one
  $("areas").innerHTML = "";
  var ulAreas = document.createElement("ul");
  $("areas").appendChild(ulAreas);
  $("spots").innerHTML = "";
  var ulSpots = document.createElement("ul");
  $("spots").appendChild(ulSpots);

  // Wm worries that this eval is a security problem.
  // This is data we're getting back from lib/ajax/MapMove.php.
  // If that has been compromised, then we really can't trust
  // anything coming from our server, which could be sending bad
  // javascript over on the original page, and not waiting for the
  // ajax call to sneak something in. But maybe I'm missing something.
  // could certainly use a custom json parser here.
  // take the json passed back from the server, and parse it into a javascript object
  var data = eval("(" + xhr.responseText + ")");

  // add each area and spot to the dom tree, and to zat.areas list of data + listeners
  var placeData,
      li;
  for (var i = 0; i < data.areas.length; i++) {
    placeData = data.areas[i];
    li = mapPlaces.areaElem(placeData);
    ulAreas.appendChild(li);
    mapPlaces.areas.push(new mapPlaces.Area(placeData, li));
  }
  for (var i = 0; i < data.spots.length; i++) {
    placeData = data.spots[i];
    li = mapPlaces.spotElem(placeData);
    ulSpots.appendChild(li);
    mapPlaces.spots.push(new mapPlaces.Spot(placeData, li));
  }
};

// ZAT_TODO: handle 2 event listeners more cleanly
mapPlaces.moveEndListener = function() {
  mapPlaces.mapMoveListener();
  saveView();
};

/**
 * Initialize the map. This is the fcn that gets called from elsewhere.
 * Initializes the global map and the <div id="map"></div>.
 * lat, lng will be center of the map, zoomed to zoom,
 * and of type (satelite, etc.) mapType
 *
 * areaAction and spotAction are functions which are passed areaData and spotData objects.
 * Whatever they return will be the innerHTML of the area/spot in the list. This
 * hook lets us configure maps on different pages to do different things when an area/spot
 * is clicked.
*/
mapPlaces.mapInit = function(lat, lng, zoom, mapType, areaAction, spotAction) {
  mapPlaces.areaAction = areaAction;
  mapPlaces.spotAction = spotAction;
  var mapobj = $('map');
  if (GBrowserIsCompatible()) {
    resizeMap();
    map = new GMap2(mapobj);
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.addControl(new GScaleControl());
    map.setCenter(new GLatLng(lat, lng), zoom, G_DEFAULT_MAP_TYPES[mapType]);
    GEvent.addDomListener(mapobj, 'DOMMouseScroll', wheelZoom);
    GEvent.addDomListener(mapobj, 'mousewheel', wheelZoom);
    GEvent.addListener(map, 'zoomend', saveView);
    GEvent.addListener(map, 'moveend', mapPlaces.moveEndListener);
    mapPlaces.mapMoveListener();
  } else {
    mapobj.innerHTML = 'your browser is unable to display <a href="http://local.google.com/support/bin/answer.py?answer=16532&topic=1499">Google Maps<\/a>.';
  }
};
 
// onclick of places, set placeId in form, and change on page too
// set placeId in form, set all class=placeName
mapPlaces.setPlaceOnClick = function(event) {
  $('placeId').value = this.data.id;
  // set everything w/ class=placeName to new name
  var elements = YAHOO.util.Dom.getElementsByClassName('placeName');
  for (var i = 0; i < elements.length; i++) {
    elements[i].innerHTML = this.data.name;
  }
};

