var ModuleGoogle = Class.create (Module, {
	initialize : function ($super, id, url)
	{
		this.name = "Google";

		$super (id, url);
	},
	showMaps : function (coordinates, zoom, options)
	{
		this.markerData = new Hash ();
		this.isCompatible = google.maps.BrowserIsCompatible ();

		if (this.isCompatible)
		{
			var defaultOptions = $H({ dragging : true, doubleClickZoom : true, scrollWheelZoom : true });
			defaultOptions = defaultOptions.merge (options).toObject ();

			var mapTypes = [];
			defaultOptions.mapTypeNormal && (mapTypes[mapTypes.length] = G_NORMAL_MAP);
			defaultOptions.mapTypeSatellite && (mapTypes[mapTypes.length] = G_SATELLITE_MAP);
			defaultOptions.mapTypeHybrid && (mapTypes[mapTypes.length] = G_HYBRID_MAP);
			defaultOptions.mapTypePhysical && (mapTypes[mapTypes.length] = G_PHYSICAL_MAP);

			this.mapObject = new google.maps.Map2 ($("module" + this.id + "Map"), { mapTypes : mapTypes });
			this.mapObject.setCenter (new google.maps.LatLng (coordinates.latitude, coordinates.longitude), zoom);
			this.mapObject.addControl (defaultOptions.menuMapTypeControl ? new google.maps.MenuMapTypeControl () : new google.maps.MapTypeControl ());

			defaultOptions.doubleClickZoom ? this.mapObject.enableDoubleClickZoom () : this.mapObject.disableDoubleClickZoom ();
			defaultOptions.scrollWheelZoom ? this.mapObject.enableScrollWheelZoom () : this.mapObject.disableScrollWheelZoom ();
			defaultOptions.dragging ? this.mapObject.enableDragging () : this.mapObject.disableDragging ();

			defaultOptions.mapControl && this.mapObject.addControl (new google.maps.LargeMapControl3D ());
			defaultOptions.overviewMapControl && this.mapObject.addControl (new google.maps.OverviewMapControl ());
			defaultOptions.scaleControl && this.mapObject.addControl (new google.maps.ScaleControl ());

			this.update ();

			google.maps.Event.bind (this.mapObject, "moveend", this, function (dummy, zoom) { this.update (); });

			Event.observe (window, "unload", google.maps.Unload);
		}
	},
	onMapData : function (results, request)
	{
		if (results.status == 200)
		{
			var data = results.responseJSON;

			if (data.length > 0)
			{
				var dataIDs = [];

				data.each (function (row) { dataIDs[dataIDs.length] = row.ID; });

				this.markerData.each (function (row) { if (dataIDs.indexOf (row.key) == -1) { this.unregister (row.key); } }, this);

				data.each (function (row) { this.register (row); }, this);
			}
		}
	},
	update : function ()
	{
		if (this.isCompatible)
		{
			var parameters = {};
			parameters.zoom = this.mapObject.getZoom ();
			parameters.latitude = this.mapObject.getCenter ().lat ();
			parameters.longitude = this.mapObject.getCenter ().lng ();
			parameters.width = this.mapObject.getBounds ().getNorthEast ().lng () - this.mapObject.getBounds ().getSouthWest ().lng ();
			parameters.height = this.mapObject.getBounds ().getNorthEast ().lat () - this.mapObject.getBounds ().getSouthWest ().lat ();

			this.getData ("point", "json", parameters, this.onMapData);
		}
	},
	register : function (data)
	{
		if (this.isCompatible)
		{
			if (!this.markerData.get (data.ID))
			{
				if (data.type == "polygon")
				{
					var polyline = [];

					for (var i = 0; i < data.coordinates.length; i ++)
					{
						polyline[polyline.length] = { color : "#000000", weight : 5, points : data.coordinates[i].polyline, levels : data.coordinates[i].level, zoomFactor : 16, numLevels : 4 };
					}

					var polygonObject = new google.maps.Polygon.fromEncoded ({ polylines : polyline, fill : true, color : "#000000", opacity : 0.4, outline : true });
					this.mapObject.addOverlay (polygonObject);
					this.markerData.set (data.ID, polygonObject);

//					var boundsObject = polygonObject.getBounds ();
//					var markerObject = new google.maps.Marker (boundsObject.getCenter ());
//					this.mapObject.addOverlay (markerObject);

					google.maps.Event.addListener (polygonObject, "click", function (latlng) {
						var boundsObject = polygonObject.getBounds ();
						this.mapObject.setCenter (boundsObject.getCenter (), this.mapObject.getBoundsZoomLevel (boundsObject));
					}.bind (this));

					google.maps.Event.addListener (polygonObject, "mouseover", function () { polygonObject.setStrokeStyle ({ color : "#ff0000" }); polygonObject.setFillStyle ({ color : "#ff0000" }); });
					google.maps.Event.addListener (polygonObject, "mouseout", function () { polygonObject.setStrokeStyle ({ color : "#000000" }); polygonObject.setFillStyle ({ color : "#000000" }); });
				}
				else if (data.type == "point")
				{
					var markerObject = new google.maps.Marker (new google.maps.LatLng (data.coordinates.latitude, data.coordinates.longitude));

					google.maps.Event.bind (markerObject, "click", this.mapObject, function () { this.openInfoWindowHtml (markerObject.getLatLng (), data.content, { maxWidth : 250 }); });

					this.mapObject.addOverlay (markerObject);

					this.markerData.set (data.ID, markerObject);
				}
			}
		}
	},
	unregister : function (ID)
	{
		if (this.isCompatible)
		{
			if (this.markerData.get (ID))
			{
				this.mapObject.removeOverlay (this.markerData.get (ID));

				this.markerData.unset (ID);
			}
		}
	}
});