/*
 * Copyright (c) 2009, webvariants GbR, http://www.webvariants.de
 * 
 * Diese Datei steht unter der MIT-Lizenz. Der Lizenztext befindet sich in der 
 * beiliegenden LICENSE Datei und unter:
 * 
 * http://www.opensource.org/licenses/mit-license.php
 * http://de.wikipedia.org/wiki/MIT-Lizenz 
 * 
 */

/**
 * Google Mapper (JS)
 * 
 * Die Klasse WV15_GMapper erzeugt eine Google Map anhand einer speziellen, 
 * objektorientierten Datenstruktur, welche per PHP erzeugt und als JSON
 * an diese Klasse gesendet wird. Ziel ist es, die komplizierte API von 
 * Google zu abstrahieren und dabei den dynamisch generierten JavaScript-Output
 * zu minimieren.
 * 
 * @author     Gregor Aisch
 * @copyright  webvariants GbR, www.webvariants.de
 * 
 */

var currentWindowHolder = null;

function WV15_Maps(data) { 
	this._data = data;
	this._map = null;
	this._bounds = null;
}

WV15_Maps.prototype.run = function() {
	if (GBrowserIsCompatible()) {
		var data  = this._data;
		this._map = new GMap2(document.getElementById(data.mapId));
		var map   = this._map;
		
		if (data.mapTypes) {
			if (data.mapTypes.selected) map.setMapType(eval(data.mapTypes.selected));
		}
		
		if (data.geoxml) {
			gx = new EGeoXml('gx', map, new Array());
		
			for (var i=0;i<data.geoxml.length;i++) {
				gx.urls.push(data.geoxml[i].kmlfilepath);
			}
			GEvent.bind(gx, 'parsed', this, this.addKMLInfoOverlayHandler);
			gx.parse();
		}
		
		
		map.setCenter(new GLatLng(parseFloat(data.mapCenter.lat), parseFloat(data.mapCenter.lng)), parseInt(data.mapZoom));
		
		
		if (data.mapBounds[0]) {
			_bounds = new GLatLngBounds();
			_bounds.extend(new GLatLng(data.mapBounds[0].lat, data.mapBounds[0].lng));
			_bounds.extend(new GLatLng(data.mapBounds[1].lat, data.mapBounds[1].lng));
			map.setZoom(map.getBoundsZoomLevel(_bounds));
			map.setCenter(_bounds.getCenter());
		}
		
		if (data.marker) {
			for (i=0;i<data.marker.length;i++) {
				var mo = {};
				mo.icon = new GIcon();
				
				if (data.marker[i].icon) {
						if (data.marker[i].icon.image) {
						mo.icon.image = data.marker[i].icon.image;
					}
					mo.icon.iconAnchor = new GPoint(data.marker[i].icon.anchor.x, data.marker[i].icon.anchor.y);
				}
				if (data.marker[i].shadow) {
					mo.icon.shadow = data.marker[i].shadow.image;
					mo.icon.infoShadowAnchor = new GPoint(data.marker[i].shadow.anchor.x, data.marker[i].shadow.anchor.y);
				}
				
				var m = new GMarker(new GLatLng(data.marker[i].coordinates.lat, data.marker[i].coordinates.lng), mo);
				
				if (data.marker[i].window) {
					mo.icon.infoWindowAnchor = new GPoint(data.marker[i].window.anchor.x, data.marker[i].window.anchor.y);
					
					m.window = data.marker[i].window;
					m._map = map;
					GEvent.bind(m, "click", m, this.openWindow);
										
					if(data.marker[i].window.showonclickid){
						GEvent.bindDom(document.getElementById(data.marker[i].window.showonclickid), "click", m, this.openWindow);
					}
				}
									
				map.addOverlay(m);
				
				if (data.marker[i].window && data.marker[i].window.show) {
					if(data.marker[i].window.type == 'G_INFO_WINDOW'){
						m.openInfoWindowHtml(m.wv_content);
					}
				}
			}
		}
		
		if (data.controls && map.setUI) {
			map.removeControl(new GMapTypeControl());
			map.removeControl(new GHierarchicalMapTypeControl());
			
			var customUI = map.getDefaultUI();
			customUI.controls.largemapcontrol3d = data.controls.largeMapControl3D;
			customUI.controls.smallzoomcontrol3d = data.controls.smallZoomControl3D;
			customUI.controls.maptypecontrol = data.controls.mapTypeControl;
			customUI.controls.menumaptypecontrol = data.controls.menuMapTypeControl;
			customUI.controls.scalecontrol = data.controls.scaleControl;
			
			if (data.controls.largeMapControl) map.addControl(new GLargeMapControl());
			if (data.controls.smallMapControl) map.addControl(new GSmallMapControl ());
			if (data.controls.smallZoomControl) map.addControl(new GSmallZoomControl());
			if (data.controls.hierarchicalMapTypeControl) map.addControl(new GHierarchicalMapTypeControl());
			if (data.controls.overviewMapControl) map.addControl(new GOverviewMapControl ());

			if (data.mapTypes) {
				customUI.maptypes.normal = data.mapTypes.g_normal_map;
				customUI.maptypes.satellite = data.mapTypes.g_satellite_map;
				customUI.maptypes.hybrid = data.mapTypes.g_hybrid_map;
				customUI.maptypes.physical = data.mapTypes.g_physical_map;
			}
			
			map.setUI(customUI);
		}

	}
}

WV15_Maps.prototype.openWindow = function(latlng) {
	if (currentWindowHolder) {
		currentWindowHolder.closeOverlay();
	}
	this.addOverlay(latlng);
}

WV15_Maps.prototype.addKMLInfoOverlayHandler = function(){
	var data = this._data;
	for(var i=0; i<gx.objects.length;i++){
		var kml_idx = parseInt(gx.objects[i]['kml_idx']);
		if(data.geoxml[kml_idx].window) {
			GEvent.clearListeners(gx.objects[i]);
			gx.objects[i].window = data.geoxml[kml_idx].window;
			GEvent.bind(gx.objects[i], 'click', gx.objects[i], this.openWindow);
			if(data.geoxml[kml_idx].window.showonclickid){
				GEvent.bindDom(document.getElementById(data.geoxml[kml_idx].window.showonclickid), "click", gx.objects[i], this.openWindow);
			}
		}
	}
}

GOverlay.prototype.addOverlay = function(latlng) {
	var map = this._map;
	if(this.window.type == 'G_INFO_WINDOW'){
		this.openInfoWindowHtml(this.window.content);
	}else if(this.window.type == 'G_OVERLAY_WINDOW'){
		if((latlng.clientX) && (typeof this.getVertex == 'function')){
			latlng = this.getVertex(0);
		}
		this.overlay = new WVOverlay(this, latlng);
		currentWindowHolder = this;
		if(typeof this.getPoint == 'function'){
			map.panTo(new GLatLng(this.getPoint().lat(), this.getPoint().lng()));
		}else {
			map.panTo(latlng);
		}
		map.addOverlay(this.overlay);
		this.overlay.show();
		if(this.window.hidemarkeronclick){
			this.hide();
		}
	}
}

GOverlay.prototype.closeOverlay = function() {
	var map = this._map;
	if(this.window.type == 'G_INFO_WINDOW'){
		this.closeInfoWindow();
	}else if(this.window.type == 'G_OVERLAY_WINDOW'){
		map.removeOverlay(this.overlay);
		if(this.window.hidemarkeronclick){
			this.show();
		}
	}
	currentWindowHolder = null;
}

var WVOverlay = function(parent, latlng) {
	this.parent = parent;
	this.latlng = latlng;
}
WVOverlay.prototype = new GOverlay();

WVOverlay.prototype.initialize = function(map) {
	var div = document.createElement("div");
	div.className = 'infowindow';
	div.innerHTML = this.parent.window.content;

	// offsets based on popup div dimensions

	this.offsetX = this.parent.window.anchor.x;
	this.offsetY = this.parent.window.anchor.y;
	
	if(typeof this.parent.getLatLng == 'function'){
		div.style.top = (map.fromLatLngToDivPixel(this.parent.getLatLng()).y - this.offsetY) + 'px';
		div.style.left = (map.fromLatLngToDivPixel(this.parent.getLatLng()).x - this.offsetX) + 'px';
	}else {
		div.style.top = (map.fromLatLngToDivPixel(this.latlng).y - this.offsetY) + 'px';
		div.style.left = (map.fromLatLngToDivPixel(this.latlng).x - this.offsetX) + 'px';
	}

	div.style.display = 'none';
	div.style.position = 'absolute';
	
	var close = document.createElement("span");
	close.className = 'close';
	div.appendChild(close);
	
	this._div = div;
	
	GEvent.bindDom(close, "click", this.parent, this.parent.closeOverlay);
	map.getPane(G_MAP_FLOAT_SHADOW_PANE).appendChild(div);
	
}

WVOverlay.prototype.show = function(){
	this._div.style.display = 'block';
}

WVOverlay.prototype.remove = function(){
	this._div.parentNode.removeChild(this._div);
}

WVOverlay.prototype.redraw = function() {
	if(typeof this.parent.getLatLng == 'function'){
		this._div.style.top = (this.parent._map.fromLatLngToDivPixel(this.parent.getLatLng()).y - this.offsetY) + 'px';
		this._div.style.left = (this.parent._map.fromLatLngToDivPixel(this.parent.getLatLng()).x - this.offsetX) + 'px';
	}else{
		this._div.style.top = (this.parent._map.fromLatLngToDivPixel(this.latlng).y - this.offsetY) + 'px';
		this._div.style.left = (this.parent._map.fromLatLngToDivPixel(this.latlng).x - this.offsetX) + 'px';
	}
}




/**
 * 
 * @param  fromAdress  			String
 * @param  toAdress  			String
 * @param  detailsContainer   	DOM-Element 	hier hängt Google die detaillierte Anfahrtsbeschreibung rein
 * @param  onComplete   		function		wird ausgeführt, nachdem die Route erfolgreich berechnet wurde
 * @param  onError   			function 		wird bei fehlern ausgeführt    
 */
WV15_Maps.prototype.showRoute = function(fromAddress, toAddress, detailsContainer, onComplete, onError) {
	if (!this._gdir) {
		this._route = {
			routeDetails: detailsContainer,
			completeHandler: onComplete,
			errorHandler: onError
		}
		this._gdir = new GDirections(this._map, detailsContainer);
		GEvent.bind(this._gdir, "load", this, this.showRouteComplete);
		GEvent.bind(this._gdir, "error", this, this.showRouteError);
	}
	this._gdir.load("from: " + fromAddress + " to: " + toAddress, { "locale": 'de' });
}

WV15_Maps.prototype.showRouteComplete = function() {
	if (this._gdir) {
		if (this._route.completeHandler) window.setTimeout(this._route.completeHandler, 200);
	}
}

WV15_Maps.prototype.showRouteError = function() {
	if (this._gdir && this._route.errorHandler) {
		this._route.errorHandler(this._gdir);
	}
}

