/**
 *  	Classe permettant de gérer unee goolgleMAP.
 *  	Version nouvelle du fichier gmapME afin de pouvoir gérer de maniere générique les évenements sur les markers.
 *   		+ suppression des variables globales JS.
 *  
 *  
 * 			var mapPointsArray=normalizeJSONArray(
 * 				[
 * 					{"lat": 48.85656, "lng": 2.350966, "nameVille" : "Paris", "idVille" : "5580", "champ": "departAllerData"},
 * 					{"lat": 37.080002, "lng": 25.15, "nameVille" : "Paros", "idVille" : "5581", "champ": "departAllerData"},
 * 					{"lat": 43.110703, "lng": 12.389172, "nameVille" : "Perouse", "idVille" : "5654", "champ": "departAllerData"},
 * 				]
 * 			);
 */

(function (){
	// On s'assure que le namespace ev.mev existe
	if(!ev.mev){ev.mev={};}	
	ev.mev.gmapMEV = [];
		
	/* Variable interne conteannt les lieux à afficher sur la map */	
	var mapPointsArray;
	
	/**
	 * Méthode à appeler avant tout utilisation. Permet d'initialiser la variable interne contenant tous les points a afficher sur la map.
	 * @param {Object} _mapPointsArray
	 */
	ev.mev.gmapMEV.init = function(_mapPointsArray) {
		mapPointsArray = _mapPointsArray;		
	};
	
	
	/**
 * Object permettant de stocker un intervalle de valeurs sous forme d'une paire numérique
 * valeur minimale et valeur maximale.
 */
	MinMax = function MinMax(_min,_max) {
	min=_min;
	max=_max;
	this.getMean=function() {
		return (min+max)/2.0;
	};
	this.getDelta=function() {
		return max-min;
	};
};
/**
 * Cette fonction permet de calculer les latitudes min et max des points listés dans la variable 
 * globale mapPointsArray stockées dans une structure MinMax. Les parametres marginTop et marginBottom
 * permettent de définir une zone ou rien ne sera affiché ( exprimés en pourcentage par rapport à la taille de la carte)
 * Dans le cas où cette variable ne contiendrait aucun point, la fonction retourne les latitudes -90 à 90.
 */
 ev.mev.gmapMEV.getLatMinMax = function(marginTop,marginBottom){ 	
	if(mapPointsArray.length==0) {return new MinMax(-90,90);}
	if(mapPointsArray.length==1) {return new MinMax(mapPointsArray[0].lng,mapPointsArray[0].lng);}
	var minMax = getLatMinMax();
	var latMax = minMax.getMean()+minMax.getDelta()/2+((minMax.getDelta()*marginTop)/(100-marginBottom-marginTop));
	var latMin = minMax.getMean()-minMax.getDelta()/2-((minMax.getDelta()*marginBottom)/(100-marginBottom-marginTop));
	return new MinMax(latMin,latMax);
};
/**
 * Cette fonction permet de calculer les latitudes min et max des points listés dans la variable 
 * globale mapPointsArray stockées dans une structure MinMax. Dans le cas où cette variable ne 
 * contiendrait aucun point, la fonction retourne les latitudes -90 à 90.
 */
ev.mev.gmapMEV.getLatMinMax = function() {	
	// Si mapPointsArray est vide
	if(mapPointsArray.length==0) return new MinMax(-90.0,90.0);
	// toute valeur de latitude (par définition inférieure à 90) diminuera 
	var latMin=90;
	for (var i=0;i<mapPointsArray.length;i++){
		if (mapPointsArray[i].lat<latMin) {
			latMin=mapPointsArray[i].lat;
		}
	}
	// Même principe pour latMax que pour latMin
	var latMax=-90;
	for (var i=0;i<mapPointsArray.length;i++){
		if (mapPointsArray[i].lat>latMax) {
			latMax=mapPointsArray[i].lat;
		}
	}
	// Si le tableau mapPointsArray était vide latMin=90, latMax=-90, et la moyenne vaut bien zéro.	
	return new MinMax(latMin,latMax);
};

function triNum(a,b) {
	return a-b;
}
/**
 * Cette fonction permet de calculer les longitudes min et max des points listés dans la variable 
 * globale mapPointsArray stockées dans une structure MinMax.Les parametres marginLeft et marginRight
 * permettent de définir une zone ou rien ne sera affiché ( exprimés en pourcentage par rapport à la taille de la carte).
 * Dans le cas où cette variable ne contiendrait aucun point, la fonction retourne les latitudes -180 à 180.
 */
ev.mev.gmapMEV.getLngMinMax = function(marginLeft,marginRight){	
	if(mapPointsArray.length==0) return new MinMax(-180,180);
	if(mapPointsArray.length==1) return new MinMax(mapPointsArray[0].lng,mapPointsArray[0].lng);
	var minMax = getLngMinMax();
	var lonMax = minMax.getMean()+minMax.getDelta()/2+((minMax.getDelta()*marginTop)/(100-marginBottom-marginTop));
	var lonMin = minMax.getMean()-minMax.getDelta()/2-((minMax.getDelta()*marginBottom)/(100-marginBottom-marginTop));
	return new MinMax(lonMin,lonMax);	
};
/**
 * Cette fonction permet de calculer les longitudes min et max des points listés dans la variable 
 * globale mapPointsArray stockées dans une structure MinMax. Dans le cas où cette variable ne 
 * contiendrait aucun point, la fonction retourne les latitudes -180 à 180.
 */
ev.mev.gmapMEV.getLngMinMax = function() {	
	if(mapPointsArray.length==0) return new MinMax(-180,180);
	if(mapPointsArray.length==1) return new MinMax(mapPointsArray[0].lng,mapPointsArray[0].lng);
	var lngSortedArray=new Array();
	for(var i=0;i<mapPointsArray.length;i++){
		lngSortedArray.push(mapPointsArray[i].lng);
	}
	lngSortedArray.sort(triNum);
	// On va chercher l'index du delta maximal, i.e. le point dont l'élongation angulaire est
	// maximale avec son prédécesseur.
	var indexDeltaMax=0;
	var deltaMax=lngSortedArray[0]-lngSortedArray[lngSortedArray.length-1]+360;
	for(var i=1;i<lngSortedArray.length;i++){
		var delta=lngSortedArray[i]-lngSortedArray[i-1];
		if(delta>deltaMax){
			deltaMax=delta;
			indexDeltaMax=i;
		}
	}
	var lngMin=lngSortedArray[indexDeltaMax];
	var lngMax;
	if(indexDeltaMax!=0){
		lngMax=lngSortedArray[indexDeltaMax-1];
	}
	else{
		lngMax=lngSortedArray[lngSortedArray.length-1];
	}
	if(lngMin>lngMax){
		lngMax+=360;
	}
	return new MinMax(lngMin,lngMax);
};
/**
 * Cette fonction permet de définir le zoom optimal en fonction de l'écart des
 * longitudes maximums et minimums
 */
	getZoomX = function(lngMinMax) {
	var width=document.getElementById("map").style.width;
	width=width.substring(0,3);
	return Math.log(width*180/40.93/lngMinMax.getDelta()/Math.PI)/Math.LN2;
};
/**
 * Cette fonction permet de définir le zoom optimal en fonction de l'écart des
 * latitudes maximums et minimums
 */
	getZoomY = function(latMinMax) {
	var height=document.getElementById("map").style.height;
	height=height.substring(0,3);
	return Math.log(height*180*Math.cos(latMinMax.getMean()*Math.PI/180)/40.93/latMinMax.getDelta()/Math.PI)/Math.LN2;
};
/**
 * Cette fonction définit le niveau de zoom en prenant la plus petite valeur entre
 * les zooms optimaux des longitudes et latitudes, et un niveau de zoom maximum.
 * Valeurs indicatives pour le zoomMax : 3 pour un continent, 5/6 pays, 7/8 region, 
 * 9/10/11 agglo, 11/12/13 ville, 14/15 quartier, 16/17 Rue.
 */
getZoomMax = function(lngMinMax,latMinMax,zoomMax) {	
	var Zx=getZoomX(lngMinMax);	
	var Zy=getZoomY(latMinMax);	
	zoomMax=Math.max(1,Math.min(17,zoomMax));
	return Math.floor(Math.min(Zx,Zy,zoomMax));
};

/**
 * Cette fonction définit le niveau de zoom en prenant la plus petite valeur entre
 * les zooms optimals des longitudes et latitudes
 * fait appel à la fonction getZoom(lngMinMax,latMinMax,zoomMax)
 * préréglé sur un niveau de zoomLMax=17 ( vue sur une rue )
 */
ev.mev.gmapMEV.getZoom = function(lngMinMax,latMinMax) {
	return getZoomMax(lngMinMax,latMinMax,17);
};

/**
 * Construicteur de l'objet marker
 * @param {Object} gpoint coordonnées du point.
 * @param {Object} nameVille nom de l'évenement. ( générifier ....)
 * @param {Object} imgMarker image à utiliser pour la representation du point.
 * @param {Object} codeVille code iata du lieu  ( générifier .... )
 * @param {Object} id id du lieu. (générifier ....)
 * @param {Object} GMAP_MARKER_EVTS tableau associatif contenant des pointers de fonction.
 * 					 var exemple = [{'click':doOnclick},{'mouseover':onMouseover}]
 * 					
 */
marker = function(gpoint, nameVille, imgMarker,codeVille,id,GMAP_MARKER_EVTS) {
	
	this.gpoint = gpoint;
	this.gmarker = new GMarker(this.gpoint, {icon : imgMarker,draggable:false, bouncy:false, dragCrossMove:false});
	this.nameVille = nameVille;
	this.codeVille = codeVille;
	this.idLieu = id;	
	var self = this.gmarker; // Fermeture
	var parent = this;
	
	
	/**
	 * Listener sur l'évenement onclick du marker de la googleMap.
	 * 
	 */  
	 GEvent.addListener(self,"click", function() {
	 	if(GMAP_MARKER_EVTS.click) {
			GMAP_MARKER_EVTS.click(parent);
		}				
	 });
	
	
	/**
	 * Cette fonction permet lors du passage du curseur sur un marqueur d'afficher dans une
	 * div le nom de la ville correspondate
	 */
  GEvent.addListener(self,"mouseover", function() {
		document.getElementById("infoBox").innerHTML = nameVille;
		document.getElementById("infoBox").style.display="block";		
		if(GMAP_MARKER_EVTS.mouseover) {
			GMAP_MARKER_EVTS.mouseover(parent);
		}		
  });

	/**
	 * Cette fonction permet lors du mouseout sur le marqueur de faire disparaitre
	 * la div précédement affichée
	 */
  GEvent.addListener(self,"mouseout", function() {
		document.getElementById("infoBox").style.display="none";
		if(GMAP_MARKER_EVTS.mouseout) {
			GMAP_MARKER_EVTS.mouseout(parent);
		}	
  });   
};

/**
 * Cette fonction permet de créer et de positionner des marqueurs sur la carte
 */
ev.mev.gmapMEV.transfertLatLngToElement = function(map,markers,latLngArray,imgMarker,GMAP_MARKER_EVTS){	
	for(var i=0;i<latLngArray.length;i++){		
		markers[i] = new marker(new GLatLng(latLngArray[i].lat,latLngArray[i].lng), latLngArray[i].nameVille, imgMarker,latLngArray[i].codeVille ,latLngArray[i].idVille,GMAP_MARKER_EVTS);			
		map.addOverlay(markers[i].gmarker);
	}
};


}());

