/**
 * Javascript for helper with methods to display GoogleMap.
 * @see GoogleMapHelper.php
 *
 * @package apps
 * @subpackage libhelper
 * @author			SVN: $Author: $
 * @version			SVN: $Id: $
 */

/**
 * Initialisation of the google map
 * Sets controls and adds markers from the global variable GMap_markers.
 *
 * Extension of GMap2-class
 * @see http://www.google.com/apis/maps/documentation/reference.html
*/
GMap2.prototype.initGujMap = function(fullControls) {
  if (fullControls || this.useFullControls) {
    //this.addControl(new GSmallMapControl());
    //this.addControl(new GMapTypeControl());
    this.addControl(new GSmallMapControl());
    this.removeMapType(G_HYBRID_MAP);
    this.addMapType(G_PHYSICAL_MAP);
    var mapControl = new GMapTypeControl();
    this.addControl(mapControl);
  }
  else {
    this.addControl(new GSmallZoomControl());
  }

  if (typeof GMap_markers != "undefined" && GMap_markers) {
  	this.updateMarkers(GMap_markers);
  }
}

GMap2.prototype.updateMarkers = function(markers) {
  this.clearOverlays();
  this.setCenter(new GLatLng(51.2443, 10.327), 5);
  if (markers) {
    this._gujMarkers = markers;
  }
  else if (typeof this._gujMarkers != "undefined" && this._gujMarkers) {
  	markers = this._gujMarkers;
  }
  else {
  	return false;
  }
  if (markers.length > 0) {
	var bounds = new GLatLngBounds();
    for (var k=0; k < markers.length; k++) {
      var marker = markers[k];
      if (marker["latitude"] != 0 && marker["longitude"] != 0) {
        var latlng = new GLatLng(marker["latitude"], marker["longitude"]);
        bounds.extend(latlng);
        //marker["gmarker"] = new GMarker(latlng);
        marker["gmarker"] = this._createMarker(latlng, marker);
        
        this.addOverlay(marker["gmarker"]);
      }
    }
    this._gujMarkers = markers; // preserve updated state

    // Extend Bounds a little to see markers at the very border
    var sw = bounds.getSouthWest();
    var ne = bounds.getNorthEast();
    var addLng = Math.abs(sw.lng() - ne.lng()) / 10;
    var addLat = Math.abs(sw.lat() - ne.lat()) / 10;
    var sw2 = new GLatLng (sw.lat() + addLat, sw.lng() + addLng);
    var ne2 = new GLatLng (ne.lat() - addLat, ne.lng() - addLng);
    bounds.extend(sw2);
    bounds.extend(ne2);

    this.setCenter(bounds.getCenter(), 15);
    while (!this.getBounds().containsBounds(bounds)) {
      this.zoomOut();
    }
  }
  else {
	  this.setZoom(6);
  }
}

/**
 * Takes latitude and longitude as parameters. If given coordinates contain
 * a marker, the map will be centered to it. Otherwise, nothing happens.
 * If the third (optional) parameter is set to true, and the marker was defined
 * with the "html" option, its info window will open with the configured content.
 * Any previously opened info window will be closed.
 *
 * @param latitude       float
 * @param longitude      float
 * @param openInfoWindow boolean (Optional, default: false) 
 */
GMap2.prototype.goToMarker = function(latitude, longitude, openInfoWindow) {
  for(var i=0; i < this._gujMarkers.length; i++) {
    var marker = this._gujMarkers[i];
    if (marker.longitude == longitude && marker.latitude == latitude) {
      this.panTo(new GLatLng(latitude,longitude));
      if (openInfoWindow) {
        this.closeInfoWindow();
        if (marker.html) {
          marker.gmarker.openInfoWindow(marker.html);
        }
      }
    }
  }
}

/**
 * Creates a marker object including info window opening on mouseover and custom icon.
 * 
 * Possible values for the options object:
 * - iconPath:       Path of the icon to use as a marker. Standard dimensions: 30x23
 * - shadow:		 Path of the image to use as the shadow.
 * - iconDimensions: Optional. Custom dimensions for the map icon, must be an object with the properties "x" and "y".
 * - html:           Optional. The HTML to be displayed within the info window. If omitted, no info window will be displayed on mouseover.
 * - clickURL:       Optional. URL to jump to when marker is clicked
 * 
 * @param options object
 * @return GMarker
 */ 
GMap2.prototype._createMarker = function(point, options) {
  if (options.iconPath) {
    var iconObject      = new GIcon(G_DEFAULT_ICON);
    iconObject.image    = options.iconPath;
    
    // Set default options:
    
    if (this._markerDefaultOptions) {
      var defaults = this._markerDefaultOptions;
      //console.log('Got defaults!');
      if (defaults.shadow) {
      	//console.log('Shadow: ' + defaults.shadow);
        iconObject.shadow = defaults.shadow;
      }
      if (defaults.iconDimensions && defaults.iconDimensions.x && defaults.iconDimensions.y) {
      	//console.log('Dimensions: ' + defaults.iconDimensions.x + 'x' + defaults.iconDimensions.y);
        iconObject.iconSize = new GSize(defaults.iconDimensions.x,defaults.iconDimensions.y);
      }
      if (defaults.iconAnchor && defaults.iconAnchor.x && defaults.iconAnchor.y) {
        iconObject.iconAnchor = new GPoint(defaults.iconAnchor.x,defaults.iconAnchor.y);
      }
      if (defaults.infoWindowAnchor && defaults.infoWindowAnchor.x && defaults.infoWindowAnchor.y) {
      	iconObject.infoWindowAnchor = new GPoint(defaults.infoWindowAnchor.x,defaults.infoWindowAnchor.y);
      }
    }
    
    // Override defaults and set specific options:

    if (options.iconDimensions && options.iconDimensions.x && options.iconDimensions.y) {
      iconObject.iconSize = new GSize(options.iconDimensions.x, options.iconDimensions.y);
    }
    else if (!iconObject.iconSize) {
      // set default dimensions if undefined and no other default set. safety net for backwards compatibility only.
      // if this class is used nowhere else then in the recommendation section, this can most probably be discarded.
      iconObject.iconSize = new GSize(30, 23);
    }
    
    if (options.shadow) {
      iconObject.shadow = options.shadow;
    }
    if (iconObject.shadow && iconObject.iconSize) {
      iconObject.shadowSize = iconObject.iconSize;
	}
	
    var markerOptions = { icon: iconObject };
    var markerObject  = new GMarker(point, markerOptions);
    
    // Add event listeners for mouseover images
    if (options.mouseoverImage) {
	  GEvent.addListener(markerObject, 'mouseover', function() {
	    markerObject.setImage(options.mouseoverImage);
	  });
	  GEvent.addListener(markerObject, 'mouseout', function() {
	    markerObject.setImage(options.iconPath);
	  });
    }
  }
  else {
  	var markerObject  = new GMarker(point);
  }

  // add event listener to open info window on click
  if (options.html) {
    GEvent.addListener(markerObject, "mouseover", function() {
      markerObject.openInfoWindowHtml(options.html);
    });
  }
  
  // go to URL on click
  if (options.clickURL) {
    GEvent.addListener(markerObject, "click", function() {
      window.location.href = options.clickURL;
    });
  }
    
  return markerObject;
}

/**
 * Sets default options for all map markers. Will be used if not overridden
 * by individual marker options.
 *
 * Possible values for the options object:
 * - shadow:		   Path of the image to use as the shadow.
 * - iconDimensions:   Optional. Custom dimensions for the map icon, must be an object with the properties "x" and "y".
 * - iconAnchor:       Pixel coordinates from the top left corner of the marker image used to anchor the marker to the map. Type: See iconDimensions.
 * - infoWindowAnchor: Pixel coordinates from the top left corner of the marker image used to anchor the info window to the marker. Type: See iconDimensions.
 *
 * @param object options
 */
GMap2.prototype.setMarkerDefaults = function(options) {
  //console.log('Defaults set!');
  this._markerDefaultOptions = options;
  this.updateMarkers();
}

/**
 * public set_marker_address
 * Update the address of an existing marker or create a new marker
 * and show the marker in the center of the map.
 * If a marker with the given ID does not exist in the list of the markers,
 * a new one is being created.
 * @param markerId int ID of an existing or the new marker
 * @param zipcode string ZIP code of the new address
 * @param city string City of the new address
 * @param street_and_number string Street and house number of the new address
 * @param function Optional callback function to deliver the resulting coordinates to, like function(marker_id, latitude, longitude){}
 *
 * Extension of GMap2-class
 * @see http://www.google.com/apis/maps/documentation/reference.html
*/
GMap2.prototype.set_marker_address = function (markerId, zipcode, city, streetAndNumber, notify) {
  address = streetAndNumber + ', ' + zipcode + ' ' + city + ', Germany';
  var geocoder = new GClientGeocoder();
  var _this = this;
  geocoder.getLocations (address, function(data) {_this.onFoundAddress(data, markerId, notify)});
}


/**
 * private
 * Called, when the data from the address search is being returned.
 *
 * Extension of GMap2-class
 * @see http://www.google.com/apis/maps/documentation/reference.html
*/
GMap2.prototype.onFoundAddress = function (data, markerId, notify) {
  var success = false;
  var marker = null;
  if (GMap_markers[markerId]) {
    marker = GMap_markers[markerId];
  }

  if (data.Status.code == 200) {
    // Find Placemark with highest Accuracy:
    var placemark = null;
    for (var p=0; p < data.Placemark.length; p++) {
      var place = data.Placemark[0];
      if (place['AddressDetails'] && place.AddressDetails['Accuracy'] >= 6) {
        if (placemark == null) {
          placemark = place;
          break;
        }
      }
    }

    // Placemark found?
    if (placemark != null) {
      var latlng = new GLatLng (placemark.Point.coordinates[1], placemark.Point.coordinates[0]);

      // Marker with that ID not in list; creating it
      if (marker == null) {
        marker = {"latitude": latlng.lat(), "longitude": latlng.lng()};
        var latlng = new GLatLng(marker["latitude"], marker["longitude"]);
        marker["gmarker"] = new GMarker(latlng);
        this.addOverlay (marker["gmarker"]);
        this.setCenter(latlng, 15);

        // Find a new markerId and put new marker in list
        markerId = GMap_markers.length;
        while (GMap_markers[markerId]) markerId++;
        GMap_markers[markerId] = marker;
      }
      else {
        marker["latitude"] = latlng.lat();
        marker["longitude"] = latlng.lng();
        marker["gmarker"].setPoint(latlng);
      }

      // show updated marker
      this.setCenter(latlng, 15);
      // Notify caller of the updated location
      if (notify) notify (markerId, latlng.lat(), latlng.lng());
      success = true;
    }
  }
}





/**
 * Initialisation of the googlemap DIV.
*/

var googlemap = false;
function gujLoadGoogleMapOnWindowLoad(fullControls) {
	if (googlemap) {
	  googlemap.useFullControls = fullControls; // override in case of event hiccups in IE
	  return true; // don't do anything if the object is already present
	}
	var div = document.getElementById("googlemap");
	if (div) {
	  if (!window.GBrowserIsCompatible || !GBrowserIsCompatible()) {
	    div.className += "browser-incompatible";
	  }
	  else {
	    googlemap = new GMap2(div);
	    googlemap.initGujMap(fullControls);
	  }
	}
}
Event.observe(window, 'load', gujLoadGoogleMapOnWindowLoad);

function update_google_map_markers (markers, fullControls) {
  gujLoadGoogleMapOnWindowLoad(fullControls); // use as singleton
  googlemap.updateMarkers(markers);
}



