/**
*	GOOGLE MAP CLASS
*
*	Classe de gestion des "Google Map" - nÃ©cÃ©ssite prototype
*
*	par LisaraÃ«l, 18 avril 2007
*/
// ==========================================================================================

/*
* Contructeur: GMapAPI()
*
*	@params:
*		- mapDiv: id de l'Ã©lÃ©ment qui va recevoir la map 		(string)
*		- gParams: objet contenant les propriÃ©tÃ©s de la map		(object)
*/
function GMapAPI(mapDiv, gParams)
{
	// déclaration des variables
	this.map;
	this.params = gParams;
	this.highlighter = (typeof gParams.highlighter != 'undefined')?gParams.highlighter:"./markers/marker_highlighter.gif";
	this.indicator = "./markers/load_indicator.gif";
	this.markersInViewport = new Array(); // futur tableau qui contiendra tous les marqueurs du viewport
	this.markersByClick = true;
	this.newMarkerParams;
	this.newIcon;
	this.hoverListPrefix = "markerList_";
	this.icons = new Array();

	// vÃ©rification de la compatibilitÃ© du browser avant la crÃ©ation de l'objet
	if ( !GBrowserIsCompatible() )
	{
		alert("Erreur: \n\nVotre navigateur n'est pas compatible avec Google Map.");
		return false;
	}

	// vÃ©rification de la prÃ©sence du container
	if( !$(mapDiv) )
	{
		alert("Erreur: \n\nLe container spÃ©cifiÃ© pour la map n'existe pas dans la page !");
		return false;
	}

	// positionnement de l'objet dans la page (servira pour plus tard)
	//$(mapDiv).setStyle( { position: 'relative' } );

	// crÃ©ation de l'objet
	this.map = new GMap2( $(mapDiv) );

	// centrage de la map sur le point dÃ©fini
	this.map.setCenter(new GLatLng(this.params.latitude, this.params.longitude), this.params.zoom);
	this.map.enableDoubleClickZoom();

	// deinition des controles
	//  1 = full, 2 = small, 3 = smallZoom, 4 = scale | 0 = rien
	switch(this.params.control)
	{
		case 1:
			this.map.addControl( new GLargeMapControl() );
			break;
		case 2:
			this.map.addControl( new GSmallMapControl() );
			break;
		case 3:
			this.map.addControl( new GSmallZoomControl() );
			break;
		case 4:
			this.map.addControl( new GScaleControl() );
			break;
	}

	if(this.params.maptype) {
		this.map.addControl( new GMapTypeControl() );
	}
	if(this.params.mapoverview) {
		this.map.addControl( new GOverviewMapControl() );
	}

	// crÃ©ation d'un objet geocoder, nommÃ© localise
	this.localise = new GClientGeocoder();

	// crÃ©ation du marker pour les highlights
	this.arrowIcon = this.createIcon({url:this.highlighter, w:15, h:20, cX: 6, cY: 60}, {url:"", w:1, h:1});
	this.arrowMarker = this.createMarker({id: 4, name:"C'est ici !", latitude: 0, longitude: 0, icon: this.arrowIcon, drag: false, info: ""});
	this.arrowMarker.hide();

	// activation des bulles d'alert sur un onclick sur la map
	if(this.params.debug) {
		GEvent.addListener(this.map, "click", function(overlay, point) {
			// $("infoPoint").update("{name:\"Mon curseur\", latitude:"+point.y+", longitude:"+point.x+", icon: homeIcon}");
			alert("CoordonnÃ©es du point :\n\nLongitude : "+point.y+"\nLatitude : "+point.x);
		});
	}

} // GMapAPI

// crÃ©ation d'un objet icÃ´ne de marqueur
GMapAPI.prototype.createIcon = function(iconObj, shadowObj)
{
	var icon = new GIcon();
		icon.image = iconObj.url;
		icon.shadow = shadowObj.url;
		icon.iconSize = new GSize(iconObj.w, iconObj.h);
		icon.shadowSize = new GSize(shadowObj.w, shadowObj.h);
		icon.iconAnchor = new GPoint(iconObj.cX, iconObj.cY);
		icon.infoWindowAnchor = new GPoint(iconObj.cX, iconObj.cY-20);

	return icon;
} // createIcon

// crÃ©ation d'un marqueur
GMapAPI.prototype.createMarker = function(obj)
{
	// vÃ©rification de la prÃ©sence d'une icÃ´ne, sinon rÃ©cupÃ©ration de l'icÃ´ne par dÃ©faut
	iconRef = ( typeof(obj.icon) == "undefined" || !obj.icon ) ? this.G_DEFAULT_ICON : obj.icon;

	// crÃ©ation du marqueur
	var marker = new GMarker(new GLatLng(obj.latitude, obj.longitude), {title:obj.name, icon:iconRef, draggable:obj.drag } );
	marker.origParams = obj;
	marker.id = obj.id;
	marker.origPoint = marker.prevPoint = marker.getPoint();

	// crÃ©ation de la bulle d'info au click si demandÃ©, avec rÃ©cupÃ©ration de contenu par ajax ou directement dans la page
	if( typeof(obj.info) == "string" ) {
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml( $(obj.info).innerHTML );
		});
	}
	else if( typeof(obj.info) == "object" && typeof(obj.info.url) == "string" )
	{
		objectRef = this;
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml('<div style="text-align: center"><br /><img alt="" src="'+this.indicator+'" /><br />chargement des infos...</div>' );

			var params = (obj.info.params != "") ? obj.info.params : "";
			new Ajax.Request(obj.info.url, {
							 		method: "post",
									// parameters: obj.info.params,
									onComplete: function(req) {
										var content = (req.responseText == "") ? '<div style="text-align: center"><br /><strong>Erreur: impossible de charger les infos.</strong></div>' : req.responseText;
										marker.openInfoWindowHtml(content);
									}
							 });
		});
	}

	// gestion du survol du marqueur et mise en surbrillance de l'Ã©lÃ©ment concernÃ© dans une liste
	objRef = this;
	objRef.saveClass = "";
	if( $(this.hoverListPrefix+obj.id) ) {
		GEvent.addListener(marker, "mouseover", function() {
			objRef.saveClass = $(objRef.hoverListPrefix+obj.id).className;
			$(objRef.hoverListPrefix+obj.id).className = "hovered";
		});
		GEvent.addListener(marker, "mouseout", function() {
			$(objRef.hoverListPrefix+obj.id).className = objRef.saveClass;
		});
	}

	// gestion de la sauvegarde (par ajax) de la position d'un marqueur aprÃ¨s un drag&drop
	if( this.params.ajaxDragSave && typeof(this.params.ajaxDragSaveUrl) == "string" ) {
		GEvent.addListener(marker, "dragend", function() {
			var newPosition = marker.getPoint();
			var newParams = $H({MarkerID: marker.id, Longitude: newPosition.x, Latitude: newPosition.y}).toQueryString();
			new Ajax.Request(objRef.params.ajaxDragSaveUrl, {parameters: newParams, onComplete: function(requester) {
				// retour d'ajax
				if( requester.responseText == marker.id )
				{
					$("marker_"+marker.id+"_latitude").update( Math.round(newPosition.y*1000000)/1000000 );
					$("marker_"+marker.id+"_longitude").update( Math.round(newPosition.x*1000000)/1000000 );
					marker.prevPoint = marker.getPoint();
					window.defaultStatus = "Nouvelle position sauvegardÃ©e.";
					new Effect.Highlight( $("markerList_"+marker.id) );
				} else {
					alert("La nouvelle position du marqueur n'a pas pu Ãªtre sauvegardÃ©e !");
					marker.setPoint( marker.prevPoint );
				}
			}});
		});
	}

	// ajout Ã  la carte
	this.map.addOverlay(marker);

	this.markersInViewport[obj.id] = marker;

	return marker;
} // createMarker

// chargement de plusieurs marqueurs
GMapAPI.prototype.loadMarkers = function(markersObj)
{
	var tempObj = this;
	$A(markersObj).each(
		function(elt) {
			elt = tempObj.createMarker(elt);
		}
	);
} // loadMarkers

// gestion de la reconnaissance d'un point depuis une adresse textuelle donnÃ©e
GMapAPI.prototype.showAddress = function(address, windowInfo, extendMap)
{
	var tempObj = this;
	this.localise.getLatLng(address, function(point) {
		if (!point) {
			alert("L'adresse \""+address+"\" \nne semble pas exister.");
		} else {
			var marker = new GMarker(point, {title: address});
			tempObj.map.addOverlay(marker);
			tempObj.markersInViewport.push(marker);
			if(extendMap)
			{
				var actualMapBounds = tempObj.map.getBounds();
				if( !actualMapBounds.contains(point) ) {
					tempObj.extendViewport(actualMapBounds);
				}
			} else {
				tempObj.map.setCenter(point, 13);
			}
			if(windowInfo) marker.openInfoWindowHtml(address+"<br />"+point);
		}
	} );
} // showAddress

// retourne les coordonnÃ©es d'une adresse
GMapAPI.prototype.addressPoint = function(address)
{
	var addPoint;
	this.localise.getLatLng(address, function(point) {
		if (!point) {
			alert("L'adresse \""+address+"\" \nne semble pas exister.");
		} else {
			addPoint = point;
		}
	} );
	return addPoint;
} // addressPoint

// Ã©tends le viewport pour qu'il contienne tous les marqueurs posÃ©s sur la carte
GMapAPI.prototype.extendViewport = function(actualMapBounds)
{
	var minLat = this.markersInViewport.min(function(elt) { return elt.getPoint().lat(); } );
	var maxLat = this.markersInViewport.max(function(elt) { return elt.getPoint().lat(); } );
	var minLng = this.markersInViewport.min(function(elt) { return elt.getPoint().lng(); } );
	var maxLng = this.markersInViewport.max(function(elt) { return elt.getPoint().lng(); } );
	var newMapBounds = new GLatLngBounds(new GLatLng(minLat, minLng), new GLatLng(maxLat, maxLng));
	var newZoomLevel = this.map.getBoundsZoomLevel(newMapBounds);
	this.map.setCenter( newMapBounds.getCenter(), newZoomLevel );
} // extendViewport

// initialise la crÃ©ation de marqueur par le click sur un point
GMapAPI.prototype.startCreateMarkersByClick = function()
{
	var mapObj = this;
	mapObj.markersByClick = GEvent.addListener(mapObj.map, "click", function(overlay, point) {
		mapObj.newMarkerParams.latitude = point.y;
		mapObj.newMarkerParams.longitude = point.x;
		mapObj.createMarker(mapObj.newMarkerParams);
	});
} // startCreateMarkersByClick

// stoppe la crÃ©ation de marqueur par le click sur un point
GMapAPI.prototype.stopCreateMarkersByClick = function()
{
	var mapObj = this;
	GEvent.removeListener(mapObj.markersByClick);
} // stopCreateMarkersByClick

// met en Ã©vidence un marqueur donnÃ©
GMapAPI.prototype.startMarkerHighlighting = function(markerId)
{
	markerPoint = this.markersInViewport[markerId].getPoint();
	actualBounds = this.map.getBounds();
	if( !actualBounds.contains( markerPoint ) ) {
		this.map.panTo(markerPoint);
	}
	this.arrowMarker.setPoint( markerPoint );
	this.arrowMarker.show();
} // startMarkerHighlighting

GMapAPI.prototype.stopMarkerHighlighting = function()
{
	this.arrowMarker.hide();
} // stopMarkerHighlighting
