SG.namespace("SG.geo");

SG.geo = function(id, geoConfig) {
	this.id = id;
	this.geoConfig = geoConfig;

	var key = this.geoConfig.geoMapKeys[window.location.host];
	var src = 'http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=' + key;
	document.write('<' + 'script src="' + src + '"' + ' type="text/javascript"><' + '/script>');

	this.markerIds = [];
	this.markers = [];
}

SG.geo.prototype.id = null;
SG.geo.prototype.geoConfig = null;
SG.geo.prototype.map = null;
SG.geo.prototype.dynamicZoomBounds = null;
SG.geo.prototype.funcPtr = [];
SG.geo.prototype.reasons = [];

SG.geo.prototype.createGeoMap = function() {
	if (GBrowserIsCompatible()) {
		this.map = new GMap2(document.getElementById(this.geoConfig.id));

		var uiOptions = this.map.getDefaultUI();

		if (this.geoConfig.enableScrollWheelZoom != null) {
			uiOptions.zoom.scrollwheel = this.geoConfig.enableScrollWheelZoom;
		}
		if (this.geoConfig.doubleClickZoom != null) {
			uiOptions.zoom.doubleclick = this.geoConfig.doubleClickZoom;
		}
		if (this.geoConfig.typeControl != null) {
			uiOptions.controls.maptypecontrol = this.geoConfig.typeControl;
		}
		if (this.geoConfig.scaleControl != null) {
			uiOptions.controls.scalecontrol = this.geoConfig.scaleControl;
		}
		if (this.geoConfig.largeMapControl != null && this.geoConfig.largeMapControl == true) {
			uiOptions.controls.largemapcontrol3d = true;
		} else {
			uiOptions.controls.largemapcontrol3d = false;
		}
		if (this.geoConfig.smallZoomControl != null && this.geoConfig.smallZoomControl == true) {
			uiOptions.controls.smallzoomcontrol3d = true;
		} else {
			uiOptions.controls.smallzoomcontrol3d = false;
		}

		this.map.setUI(uiOptions);

		this.dynamicZoomBounds = new GLatLngBounds();

		// ====== Array for decoding the failure codes ======
		this.reasons[G_GEO_SUCCESS] = "Success";
		this.reasons[G_GEO_MISSING_ADDRESS] = "Missing Address: The address was either missing or had no value.";
		this.reasons[G_GEO_UNKNOWN_ADDRESS] = "Unknown Address:  No corresponding geographic location could be found for the specified address.";
		this.reasons[G_GEO_UNAVAILABLE_ADDRESS] = "Unavailable Address:  The geocode for the given address cannot be returned due to legal or contractual reasons.";
		this.reasons[G_GEO_BAD_KEY] = "Bad Key: The API key is either invalid or does not match the domain for which it was given";
		this.reasons[G_GEO_TOO_MANY_QUERIES] = "Too Many Queries: The daily geocoding quota for this site has been exceeded.";
		this.reasons[G_GEO_SERVER_ERROR] = "Server error: The geocoding request could not be successfully processed.";

		for ( var i = 0; i < this.geoConfig.geoMarkers.length; i++) {
			var geoMarker = this.geoConfig.geoMarkers[i];
			if (geoMarker.latitude == 0 && geoMarker.longitude == 0) {
				var geocoder = new GClientGeocoder();
				var address = this._formatAddress(geoMarker.street, geoMarker.postcode, geoMarker.city,
						geoMarker.country);
				var idstr = "" + this.id;
				this.funcPtr[i] = new Function("point", "SG.geo." + this.id + "._latLngCallback.call(SG.geo." + this.id
						+ ", point, " + i + ");");
				geocoder.getLocations(address, this.funcPtr[i]);
			} else {
				var point = new GLatLng(geoMarker.latitude, geoMarker.longitude);
				this.map.setCenter(point, this.geoConfig.zoom);

				var markerId = "";
				var iconUrl = geoMarker.icon;
				if (iconUrl != undefined && iconUrl != "null" && iconUrl != "" && iconUrl.indexOf('?') != -1) {
					markerId = iconUrl.substring(iconUrl.indexOf('?')+1, iconUrl.length);
					iconUrl = iconUrl.substring(0, iconUrl.indexOf('?'));
				}
				
				var marker = this._createMarker(point, 0, geoMarker.name, geoMarker.description, geoMarker.link,
						iconUrl, geoMarker.iconAnchorWidth, geoMarker.iconAnchorHeight, geoMarker.clickable,
						geoMarker.draggable, geoMarker.bouncy, geoMarker.callbackMethodDraggend, null);
				
				this.map.addOverlay(marker);
				
				this.markerIds.push(markerId);
				this.markers.push(marker);

				this.dynamicZoomBounds.extend(point);
			}
		}

		if (this.map.getZoom() < 2) { // dynamic zoom
			var zoomLevel = this.map.getBoundsZoomLevel(this.dynamicZoomBounds);
			if (zoomLevel > 13) {
				zoomLevel = 13;
			}
			this.map.setZoom(zoomLevel);
		}
	}
}

SG.geo.prototype._formatAddress = function(street, postcode, city, country) {
	var address = "";
	if (!SG.cal.util.isEmpty(street)) {
		address = street + ", ";
	}
	if (!SG.cal.util.isEmpty(postcode)) {
		address += postcode + ", ";
	}
	if (!SG.cal.util.isEmpty(city)) {
		address += city + ", ";
	}
	if (!SG.cal.util.isEmpty(country)) {
		address += country;
	}
	return address;
}

SG.geo.prototype._createMarker = function(point, colorNr, name, description, link, iconUrl, iconAnchorWidth,
		iconAnchorHeight, isClickable, isDraggable, isBouncy, callbackMethod, size) {
	var icon = new GIcon();
	if (iconUrl != undefined && iconUrl != "null" && iconUrl != "") {
		icon.image = iconUrl;
	} else {
		if (colorNr == 1) {
			icon.image = "http://labs.google.com/ridefinder/images/mm_20_yellow.png";
		} else {
			icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
		}
	}
	// icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
	// icon.shadowSize = new GSize(22, 20);
	icon.iconAnchor = new GPoint(iconAnchorWidth, iconAnchorHeight);
	icon.infoWindowAnchor = new GPoint(5, 1);

	if (size) {
		icon.iconSize = new GSize(size, size);
	}

	/*
	 * Attention: even if isClickable is set to false, it should be set to true here. Non-clickable GMarkers don't
	 * support mouseover and mouseout eventlisteners. If the parameter isClickable is set to false, no eventlistener for
	 * 'click' will be registered.
	 */

	var options = {
		icon : icon,
		clickable : true,
		draggable : isDraggable,
		bouncy : isBouncy
	}

	var marker = new GMarker(point, options);

	if (isClickable) {
		GEvent.addListener(marker, "click", function() {
			var nameContent;
			var descriptionContent;

			if (description != undefined && description != "null" && description != "") {
				descriptionContent = '<br><div style="font-size:10; text-decoration: none;" > ' + description
						+ "</div>";
			} else {
				descriptionContent = "";
			}

			if (link != undefined && link != "null" && link != "") {
				nameContent = '<a href="' + link + '"> <b>' + name + "</b>" + descriptionContent + "</a>";
			} else if (name != "null" && name != "" && name != undefined) {
				nameContent = "<b>" + name + "</b>" + descriptionContent;
			}

			var content = nameContent;
			marker.openInfoWindowHtml(content);
		});
	}

	if (isDraggable) {
		GEvent.addListener(marker, "dragend", function(p1) {
			marker = p1;
		});

		if (callbackMethod != null) {
			GEvent.addListener(marker, "dragend", eval(callbackMethod));
		}
	}

	// only for FV
	// ------------
	GEvent.addListener(marker, "mouseover", function() {
		FV.showVereinInErgebnisse(name.replace(";", " "));
		FV.showVereinInTabellen(name.split(";")[0]);
		FV.showVereinInTabellen(name.split(";")[1]);
	});
	GEvent.addListener(marker, "mouseout", function() {
		FV.hideSelectedRows();
	});
	// ------------

	return marker;
}

SG.geo.prototype._latLngCallback = function(result, id) {
	var geoMarker = this.geoConfig.geoMarkers[id];
	if (result.Status.code == G_GEO_SUCCESS) {
		this.funcPtr[id] = null;
		var p = result.Placemark[0].Point.coordinates;
		var point = new GLatLng(p[1], p[0]);
		this.map.setCenter(point, this.geoConfig.zoom);

		this.map.addOverlay(this._createMarker(point, 0, geoMarker.name, geoMarker.description, geoMarker.link,
				geoMarker.icon, geoMarker.iconAnchorWidth, geoMarker.iconAnchorHeight, geoMarker.clickable,
				geoMarker.draggable, geoMarker.bouncy, geoMarker.callbackMethodDraggend, null));
	} else {
		var address = this._formatAddress(geoMarker.street, geoMarker.postcode, geoMarker.city, geoMarker.country);
		/*
		 * var reason="Code "+result.Status.code; if (this.reasons[result.Status.code]) { reason =
		 * this.reasons[result.Status.code] } alert('Could not find "' + address + '" ' + reason);
		 */

		if (result.Status.code != G_GEO_UNKNOWN_ADDRESS) {
			var geocoder = new GClientGeocoder();
			geocoder.getLocations(address, this.funcPtr[id]);
		}
	}
}