/**
 *
 */
 
XELocation = window['XELocation'] || {}; 
XELocation.addMapDataHandler = function(mapData, options) {
  options = Object.extend({ 
    icon: XELocation.getMapDataIcon(mapData),
    errorHandler: function(mapData) { console.error(mapData.Address + " not found"); }
  }, options || {});
  
  mapData.toString = XELocation.toString;
  var me = this;
  var map = this.map;
  var marker = null;
  var addPoint = (function(point) {
    marker = new GMarker(point, options);
    if (mapData.Description) {
      GEvent.bind(marker, 'click', this, function(arg1) {
        marker.openInfoWindowHtml(mapData.Description);
      });
    }
    
    if(options.manager) {
      options.manager.addMarker(marker, 6);
      options.manager.refresh();
    } else map.addOverlay(marker);
    if(options.draggable) marker.enableDragging();
    if(options.centre) XELocation.centreOnMarker.call(me, mapData, marker);
    if(options.onAdded) options.onAdded.call(me,marker, mapData);

    return marker;
  }).bind(this);
  
  // TODO Check for correct type of MapData, i.e. anything derived from XELocation.
  if (mapData.Lat && mapData.Lng) {
    return addPoint(new GLatLng(mapData.Lat, mapData.Lng));
  } else if(mapData.Address) {
    var geocoder = new GClientGeocoder();
    geocoder.getLatLng(mapData.Address,
    function(point) {
      if (!point) {
        options.errorHandler(mapData);
      } else {
        return addPoint(point);
      }
    });
    return addPoint;
  } else {
    console.error("XELocation %o doesn't have a Lat/Lng or an address", mapData);
  }
}

XELocation.icons = XELocation.icons || {};


XELocation.getMapDataIcon = function(mapData) {
  var ClassName = mapData.ClassName;
  if(!XELocation.icons[ClassName]) ClassName = "XELocation";
  
  if(XELocation.icons[ClassName]) {
    return XELocation.icons[ClassName];
  } else {
    return new GIcon(G_DEFAULT_ICON);
  }
}
  
XELocation.centreOnMarker = function(mapData, marker) {
  this.map.setZoom(parseInt(mapData.Zoom));
  this.map.panTo(marker.getPoint());
}

XELocation.editor = XELocation.editor || {};
XELocation.editor.addMapDataHandler = function(mapData, options) {
  var callback = options.callback;
  var me = this;
  var optionsCopy = Object.clone(options);
  var marker = XELocation.addMapDataHandler.bind(this)(mapData, 
    Object.extend(optionsCopy, {clickable: true, draggable: true, centre: true,
      onAdded:   function(marker) {
        GEvent.bind(marker, 'dragend', me, function() {
          var location = marker.getLatLng();
          mapData.Lat = location.lat();
          mapData.Lng = location.lng();
          mapData.Address = false;
          callback(mapData);
        });
        callback({
          Lat: marker.getPoint().lat(), 
          Lng: marker.getPoint().lng(),
          Address: mapData.Address ? mapData.Address : false
        });
      }
    })
  );
  return marker || true;
  // TODO try to reuse more of the default display behaviour implemented in XELocation
}
XELocation.editor.centreOnMarker = XELocation.centreOnMarker;

XELocation.editor.initMapDataHandler = function(options) {
  var callback = options.callback;
  GEvent.bind(this.map, 'click', this, function(overlay, point) {
    if (!overlay) {
      // TODO Get rid of old markers
      if(this.getMapData().length < 1) {
        var mapData = {ClassName: "XELocation", Lat: point.lat(), Lng: point.lng()};
        this.addMapData(mapData);
        callback({Lat: point.lat(), Lng: point.lng()});
      }
    }
  });
  GEvent.bind(this.map, 'zoomend', this, function(oldLevel, newLevel) {
    callback({Zoom: newLevel});
  });
  
}

XELocation.toString = function() {
  if(this.Address) {
    return this.Address;
  } else if(this.Lat && this.Lng) {
    return this.Lat + "," + this.Lng;
  } else {
		//console.log("No Address or Lat/Lng for %o", this);
  }
}
