/**
FRAMEWORK GMAP V3 BAPTISTE GAUTHIER

 * @fileOverview Un objet pour manipuler des GmapV3
 * @name Map
 */



/*
TODO 
- localis entreprise
- completer centerWithAddress
- voir pour mettre dans la classe location centerWithAddress
- changer le max zoom en fonction du typê de map
- getElevation parametre polyline ou array
*/

/**
 * Creer une map
 *
 * NOTE: Constructeur de l'objet Map
 * @constructor
 * @param {String} id string représentant l'id de la div où va être positionné la map
 * @param {Object} options qui parametre la map (positionement, déplacement...)
  * @param {Object} controleurs qui sert à manipuler la carte
 */

function Map(id, options, controleurs) {
	
	
	this.map = null;
	this.id_map = id;
	this.cursorScroll_id = null;
	this.fondScroll_id = null;
	this.style ="background-color:#e5ecf9";
	this.maxZoom = 22;
	this.t_style = 0;
	
	

		
	this.def = {
		zoom : 2,
		center : {
			lat : 45.5,
			lng : 5.3
		},
		type :'ROADMAP'
	};
	
	options = Utils.extend(this.def,options);
	
	this.defControl = {
		hidden : false,
		scale : false,
		type: true,
		dblClickZoom : true,
		scrollZ : false,
		draggable : true
	};
	
	controleurs = Utils.extend(this.defControl,controleurs);
	
	this.deplacement =100;
	try
	{
		
		
		var opt = new Object();
		opt = Utils.extend(this.def,options);
		opt.center =  new google.maps.LatLng(options.center.lat, options.center.lng);
		opt.mapTypeId =  google.maps.MapTypeId[options.type];
	
		opt.draggable= controleurs.draggable;
		opt.disableDefaultUI= controleurs.hidden;
		opt.scaleControl= controleurs.scale;
		opt.mapTypeControl= controleurs.type;
		
		if(typeof(controleurs.dblClickZoom) != "undefined"){
			opt.disableDoubleClickZoom	= controleurs.dblClickZoom;
		}
		if(typeof(options.scroll) != "undefined"){
			opt.scrollwheel =  options.scroll;
		}
		
			
		
		
		this.map = new google.maps.Map(document.getElementById(this.id_map),opt);
			
			
			
	
				
	}
	catch(e)
	{
		Utils.debug("class MAP : iniatilisation",e);
	}
			
}




/**
 * Ajouter un évènement à la map
 *
 * @param {Object} type type d'évènement
 * @param {Object} functfunction pour le callback
 */
Map.prototype.addEvent = function(type,funct){	
	google.maps.event.addListener(this.map, type, funct);
}

/**
 * Ajouter un évènement a un object
 *
 * @param {Object} obj object sur lequel ajouter un événement
 * @param {String} type évènement
  * @param {String} funct fonction à executer après l'évènement capturé
 */
Map.prototype.addEventOnObject = function(obj,type,funct){   
    google.maps.event.addListener(obj, type, funct);
}

/**
 *Configuration des bulles
 *
 * @param {String} style css du contener de la bulle custom
 */
Map.prototype.confInfoBulle = function(style){	
	this.style =style;
}




/**
 * ajouter un polyline
 *
 *
 *
 * @param {Array} t_latLng 
 * @param {Object} option
 */
Map.prototype.addPolyline = function (t_latLng,option)
{
	
	var o = {
		color:"#FF0000",
		alpha : 1,
		size:3
	}
	
	option = Utils.extend(o, option);
	
		if(t_latLng.length > 0){
			
			var polyline = new google.maps.Polyline({
			  path: t_latLng,
			  strokeColor: option.color,
			  strokeOpacity: option.alpha,
			  strokeWeight: option.size
			});
		
		   polyline.setMap(this.map);

		}
		
		return polyline;
}


Map.prototype.addPolygone = function (t_latLng,option)
{
	
	var o = {
		sColor: "#FF0000",
		sAlpha: 1,
		sSize: 1,
		fColor: "#FF0000",
		fAlpha: 1
	}
	
	option = Utils.extend(o, option);
	
		if(t_latLng.length > 0){
			
			var polyline = new google.maps.Polygon({
				paths: t_latLng,
				strokeColor: option.sColor,
				strokeOpacity: option.sAlpha,
				strokeWeight: option.sSize,
				fillColor: option.fColor,
				fillOpacity: option.fAlpha
			});
		
		   polyline.setMap(this.map);

		}
	
		return polyline;
}




/**
 * ajouter un MarkerHTML
 *
*. c'est objet utilise la class richmarker http://code.google.com/p/google-maps-utility-library-v3/
 *
 * @param {Float} lat latitude du point
  * @param {Float} lng longitude du point
 * @param {String} html HTML pour créer le marker
 * @param {Function} func
 */
Map.prototype.addMarkerHTML = function (lat,lng,html,func)
{
	
	if(lat != "" && lng != "" && html != "" ){
		var marker = new RichMarker({
          position: new google.maps.LatLng(lat, lng),
          map: this.map,
          draggable: false,
          content: html,
		  anchor : [50,0]
        });
		
		
		google.maps.event.addListener(marker, 'click', function() {
															
         	if(typeof(func) == "function"){
				func();	
			}
        });
		
		return marker;
	}else{
		Utils.trace("Les paramètres passés à la fonction addMarkerHTML ne sont pas correctes.");	
	}
}


/**
 * ajouter un marker
 *. : pour fermer la bulle vous pouvez utiliser cette fonction marker.bulle.setMap(null). C'est objet utilise la class infoBox http://code.google.com/p/google-maps-utility-library-v3/ (mais attention cette classe a été adaptée pour une utilisation particuliere).
 * @param {Object} options
 */
Map.prototype.addMarker = function (options)
{
	
	var self = this;
	var o = {
		ancreX : 0,
		ancreY : 0,
		title : ''
	};
	
	options = Utils.extend(o,options);
	
	try
	{
		
				
				
		if(typeof(options.lat) != 'undefined' && typeof(options.lng) != 'undefined'){
					
					
					var optCenterMarker = new google.maps.LatLng(options.lat, options.lng);
					
					
					if(typeof(options.width) != "undefined" && typeof(options.height) != "undefined" && typeof(options.img) != 'undefined' && options.img != ""){
					 	
						var icon = options.img;
						icon = new google.maps.MarkerImage(options.img,  new google.maps.Size(options.width,options.height),
						  // origine
						  new google.maps.Point(0,0),
						  // ancre
						  new google.maps.Point(options.ancreX,options.ancreY));

					}
					
					var optMarker ={
						position : 	optCenterMarker,
						title : 	options.title,
						map : 		this.map
					};
					
					if(typeof(icon) != "undefined"){
						optMarker = Utils.extend(optMarker,{icon:icon});
					}
					if(typeof(options.draggable) != "undefined" ){
                        optMarker = Utils.extend(optMarker,{draggable:options.draggable});
                    }
					
					
					var marker = new google.maps.Marker(optMarker);
					
					if(typeof(options.infoBulle) != 'undefined' && options.infoBulle != null){
						
						var o2 = {
							ancreX : 0,
							ancreY : 0
						};
						
						options.infoBulle = Utils.extend(o2, options.infoBulle);
						
						
						if(typeof(options.infoBulle.func) != 'undefined'){
							marker.func = options.infoBulle.func;
							
						}
						
						if(typeof(options.infoBulle.text) != 'undefined' && options.infoBulle.text != ""){
							marker.info = options.infoBulle.text;
							
						}
						
							marker.ancreX = options.infoBulle.ancreX;
							marker.ancreY = options.infoBulle.ancreY;
							
						
						
					}else{
						if(typeof(options.text) != "undefined"){
							var infowindow = new google.maps.InfoWindow({
								content: options.text
							});
							marker.infoWindow = infowindow;
						}
					}
					
					
					
					google.maps.event.addListener(marker, 'click', function()
					{
						if(typeof(this.info) != 'undefined' && this.info != ""){
							
							self.ouvreBulleCustom(this);


						}
						
						
						if(typeof(this.infoWindow) != 'undefined'){
							
							//TODO faire comme pour les bulle custom
							this.infoWindow.open(self.map,this);
						}
						
						if(typeof(this.func) != 'undefined' ){
							
							if(typeof(this.func) == 'function'){
								
								this.func();
							} else{
								try{
									
									eval(this.func);
								}catch(e){
									Utils.debug("class MAP : ajout marker action function erreur ",e);
								}
							}
						}
					});
					
					
				
			return marker;
		}
	}catch(e){
		Utils.debug("class MAP : add marker", e);	
	}
	/*
	//bounds.extend(optCenterMarker);
	marker[i][j] = 
	google.maps.event.addListener(marker[i][j], 'click', function()
		{
			tabInfo[i][j].open(carte, marker[i][j]);
		});
	//carte.fitBounds(bounds);*/
}


/**
 * ouverture d'une bulle pour un maker custom
 *
 * @param {Marker} marker pour lequel il faut ouvrir la bulle
 */

Map.prototype.ouvreBulleCustom = function(marker){
	
	if(typeof(marker.infoWindow) != "undefined"){
		marker.infoWindow.open(this.map,marker);
		return;	
	}
	
		/*marker.bulle = new InfoBox({
			latlng: marker.getPosition(), 
			map: this.map,
			content:marker.info, 
			ancreX: marker.ancreX, 
			ancreY :marker.ancreY,
			style:self.style
		})*/;	
	if(typeof(marker.bulle) == "undefined"){
		var myOptions = {
			 content: marker.info
			,disableAutoPan: false
			,maxWidth: 0
			,pixelOffset: new google.maps.Size(marker.ancreX, marker.ancreY)
			,zIndex: 1
			,isHidden: false
			,pane: "floatPane"
			,enableEventPropagation: false
		};
		
		marker.bulle = new InfoBox(myOptions);
		marker.bulle.open(this.map, marker);
	}else{
		marker.bulle.open(this.map, marker);
	}
}





/**
 * Initialisation d'un controlleur de zoom personnalisé
 *
 * @param {String} id_zoom_plus
  * @param {String} id_zoom_moins
 */
Map.prototype.initZoom = function (id_zoom_plus, id_zoom_moins)
{
	var self = this;
	try{
			
			if(id_zoom_plus != null ){
				google.maps.event.addDomListener(document.getElementById(id_zoom_plus), 'click', function() { self.zoom('plus'); });
			};
			if(id_zoom_moins != null ){
				google.maps.event.addDomListener(document.getElementById(id_zoom_moins), 'click', function() { self.zoom('moins'); });
			};
		
	}catch(e){
		Utils.debug("class MAP : init Zoom", e);	
	}
}



/**
 * Initialisation d'un controlleur de type de map personnalisé
 *
 * @param {String} id_c
  * @param {String} id_s
   * @param {String} id_h
  * @param {String} id_p
 */
Map.prototype.initTypeControl = function (id_c, id_s,id_h, id_p)
{
	var self = this;
	try{
			
			if(id_c != null ){ 
				google.maps.event.addDomListener(document.getElementById(id_c), 'click', function() { self.changeType(google.maps.MapTypeId['ROADMAP']); });
			};
			if(id_s != null ){
				google.maps.event.addDomListener(document.getElementById(id_s), 'click', function() { self.changeType(google.maps.MapTypeId['SATELLITE']); });
			};
			if(id_h != null ){
				google.maps.event.addDomListener(document.getElementById(id_h), 'click', function() { self.changeType(google.maps.MapTypeId['HYBRID']); });
			};
			if(id_p != null ){
				google.maps.event.addDomListener(document.getElementById(id_p), 'click', function() { self.changeType(google.maps.MapTypeId['TERRAIN']); });
			};
		
	}catch(e){
		Utils.debug("class MAP : init control type", e);	
	}
}


/**
 * Initialisation d'un controlleur de zoom personnalisé (scrollbar)
 *
 * @param {String} id_scroll
  * @param {String} id_fond
 */
Map.prototype.initScrollZoom = function(id_scroll, id_fond)
{
		var self = this;
		try
		{
			if(id_scroll != "" && id_fond != ""){
				this.cursorScroll_id = id_scroll;
				this.fondScroll_id = id_fond;
				//this.placeCursorScroll(-1);
				google.maps.event.addDomListener(document.getElementById(id_fond), 'click', function(e){self.clickFond(e)});
				this.placeCursorScroll(this.getZoom());
			}
			this.addEvent("zoom_changed",function(){self.placeCursorScroll(-1)})
			
		}catch(e){
			Utils.debug("class MAP : init control SCROLL ZOOM", e);	
		}

}


/**
 * Initialisation d'un controlleur de déplacement personnalisé 
 *
 * @param {String} id_u
  * @param {String} id_l
  * @param {String} id_d
  * @param {String} id_r
 */
Map.prototype.initDeplacementControl = function (id_u, id_l,id_d, id_r)
{
	var self = this;
	try{
			
			if(id_u != null ){ 
				google.maps.event.addDomListener(document.getElementById(id_u), 'click', function() { self.deplace("up"); });
			};
			if(id_l != null ){
				google.maps.event.addDomListener(document.getElementById(id_l), 'click', function() { self.deplace("left"); });
			};
			if(id_d != null ){
				google.maps.event.addDomListener(document.getElementById(id_d), 'click', function() { self.deplace("down"); });
			};
			if(id_r != null ){
				google.maps.event.addDomListener(document.getElementById(id_r), 'click', function() { self.deplace("right"); });
			};
		
	}catch(e){
		Utils.debug("class MAP : init control type", e);	
	}
}



/**
 * Initialisation d'un controlleur de zoom au drag
 *.:C'est objet utilise la class keydragzoom http://code.google.com/p/google-maps-utility-library-v3/
 *
 * @param {Objet} opts
 */
Map.prototype.initDragZoom = function (opts)
{
	try{
		
		var widthBorder = 1;
		if(typeof(opts) == "object"){
			if(typeof(opts.widthBorder) != "undefined"){
				widthBorder = opts.widthBorder;
			}
		}
		
		var borderColor = "black";
		if(typeof(opts) == "object"){
			if(typeof(opts.borderColor) != "undefined"){
				borderColor = opts.borderColor;
			}
		}
		
		var backColor = "red";
		if(typeof(opts) == "object"){
			if(typeof(opts.backColor) != "undefined"){
				backColor = opts.backColor;
			}
		}
		
		var alpha = 0.35;
		if(typeof(opts) == "object"){
			if(typeof(opts.alpha) != "undefined"){
				alpha = opts.alpha;
			}
		}
		
		
		this.map.enableKeyDragZoom({
            key: "shift", 
            boxStyle: {
              border: widthBorder+"px dashed "+borderColor,
              backgroundColor: "transparent",
              opacity: 1.0
            },
            veilStyle: {
              backgroundColor: backColor,
              opacity: alpha,
              cursor: "crosshair"
            },
            visualEnabled: false
        });
		
	}catch(e){
		Utils.debug("class MAP : init drag zoom", e);	
	}
}

















/**
 * Action de zoom
 *
 * @param {String} type
 */
Map.prototype.zoom = function (type)
{
	var zoom;
	try
	{
		if(type == "moins"){
			zoom = (this.getZoom()-1);
		}
		if(type == "plus"){
			zoom = (this.getZoom()+1);
		}
		this.setZoom(zoom);
		
	}catch(e){
		Utils.debug("class MAP : probleme sur le zoom", e);	
	}
	
}
/**
 * Action de changement de type de map
 *
 * @param {MapTypeID} mapTypeId
 */
Map.prototype.changeType = function (mapTypeId)
{
	try{
		this.setMapTypeId(mapTypeId);
	}catch(e){
		Utils.debug("class MAP : probleme sur le changement de type", e);	
	}
}
/**
 * Action de deplacement de map
 *
 * @param {String} type
 */
Map.prototype.deplace = function (type)
{
	try
	{
		var deplacementX = 0;
		var deplacementY = 0;
		switch(type)
		{
			case 'up':
				deplacementX = 0
				deplacementY = -this.deplacement;
				break;
			case 'down':
				deplacementX = 0
				deplacementY = this.deplacement;
				break;
			case 'left':
				deplacementX = -this.deplacement
				deplacementY = 0;
				break;
			case 'right':
				deplacementX = this.deplacement
				deplacementY = 0;
				break;
		}
		this.panBy(deplacementX,deplacementY);
	}
	catch(e)
	{
		Utils.debug("class MAP : probleme sur le deplacemnt de la carte", e);	
	}
	
}
/**
 * Détection de l'emplacement du click sur la scrollbar de zoom
 *
 * @param {Event} e
 */
Map.prototype.clickFond = function(e) 
{ 
	try
	{
		
		var hauteur_fond = document.getElementById(this.fondScroll_id).offsetHeight;
	   
	   var bord_haut_fond = Utils.getY(this.fondScroll_id);
	   
	   var bord_haut_curseur= null ; 
	  if(typeof(e.pageY) != 'undefined')
	  {
		bord_haut_curseur = e.pageY;
	  }
	  else
	  {
		  bord_haut_curseur = e.clientY;
	  }
	   var delta = (hauteur_fond)-(parseInt(bord_haut_curseur) - parseInt(bord_haut_fond));
	   
	   
	   /*TODO  max zoom */
	   var zoomSuiv = parseInt(Math.abs(delta *this.maxZoom / hauteur_fond));
	   this.setZoom(zoomSuiv);
	   this.placeCursorScroll(parseInt(zoomSuiv));
		
		
	}
	catch(e)
	{
		Utils.debug("class MAP : init control clic on scroll", e);	
	}
}

/**
 * Position du slider de la scrollbar
 *
 * @param {Integer} zoomParticulier
 */
Map.prototype.placeCursorScroll = function(zoomParticulier)
{
	try
	{
		
		var zoomEncour = 0;
		if(zoomParticulier == -1)
		{
			zoomEncour = this.getZoom();
		}
		else
		{
			zoomEncour = zoomParticulier;
		}
		
		if(this.fondScroll_id != null && this.fondScroll_id != "" && typeof(document.getElementById(this.fondScroll_id)) != 'undefined'){
			var hauteurFond = document.getElementById(this.fondScroll_id).offsetHeight;
	   		
			 /*TODO  max zoom */
			var hauteurJauge = (hauteurFond/this.maxZoom)*zoomEncour;
			document.getElementById(this.cursorScroll_id).style.height = hauteurJauge+'px';
			
		}
	}
	catch(e)
	{
		Utils.debug("Une erreur a été detecter durant l'affectation d'un zoom nouveau au scroll (class gmapNQ)",e)
	}
	
}









/**
 * Centrer la map avec un polyline
 *
 * @param {Polyline} poly
 */
Map.prototype.centerWithPoly = function(poly){
	var path = poly.getPath();
	var bounds = new google.maps.LatLngBounds();
	if(path.length > 0){
		for(var i = 0 ; i < path.length; i++){
			
			 bounds.extend(path.getAt(i));	
		}
			
			  //alert(bounds.getCenter());
		this.map.fitBounds(bounds);

	}


}


/**
 * Centrer la map avec un tableau de marker
 *
 * @param {Array} markers
 */
Map.prototype.centreWithMarker = function(markers){
	
	try{
		
		var bounds = new google.maps.LatLngBounds();
		if(markers.length > 0){
			for(var i = 0 ; i < markers.length; i++){
				
				 bounds.extend(markers[i].getPosition());	
			}
			
			  //alert(bounds.getCenter());
			  this.map.fitBounds(bounds);
		}
	}
	catch(e)
	{
		Utils.debug("class Map : centre marker ",e);
	}
	
}



/**
 * Centrer la map avec une adresse postale
 *
 * @param {String} address
 */
 
Map.prototype.centerWithAddress = function(address) {
 //TODO a completer et etudier code ci dessous
        /*var mymap = this.gmap;
        this.geocoder.geocode({ 'address': address }, function(results, status) {
 
            if (status == google.maps.GeocoderStatus.OK) {
                mymap.set_center(results[0].geometry.location);
 
                type = results[0].geometry.location_type;
 
                zoom = 13;
                if (type == google.maps.GeocoderLocationType.ROOFTOP) {
                    zoom = 17;
                }
                else if (type == google.maps.GeocoderLocationType.INTERPOLATED) {
                    zoom = 17;
                }
                else zoom = 13;
 
                //mymap.set_zoom(zoom);
            }
            //else alert("Erreur : " + status);
        });
    }
	
	 this.clearMarkersOutOfView = function() {
 
        bounds = this.gmap.get_bounds();
 
        for (var i in this.tabMarker) {
 
            marker = this.tabMarker[i];
            latLng = marker.get_position();
 
            if (!bounds.contains(latLng)) {
                this.tabMarker[i].set_map(null);
                delete (this.tabMarker[i]);
            }
        }*/
 }


/**
 * Obtenir élévation d'un tableau de lat lng
 *
 * @param {Array} t_latlong
  * @param {Function} func
 */
Map.prototype.getElevation = function(t_latlong,func){
	
	try{
		var elevationService = new google.maps.ElevationService();

		
		if(typeof(t_latlong) != "array"){
			t_latlong = t_latlong.getPath().getArray() ;
		}
		
		
		elevationService.getElevationAlongPath({
          path: t_latlong,
          samples: 256
        }, function(results){
			
			func(results);
    
				


		});
	}
	catch(e)
	{
		Utils.debug("class Map : get elevation markers ",e);
	}
	
}


/**
 * Modification du style des carte Google map
 *
 * 
 */
Map.prototype.setStyle = function(style,options){
	
	var o = {
		name : "monstyle",
		nameStyle : "monstyleMap"
	};
	
	options = Utils.extend(o,options);
	
	var styledMapOptions = {name: options.name};
	var monMapType = new google.maps.StyledMapType(style, {name: options.name});
	this.map.mapTypes.set(options.nameStyle, monMapType);
	this.map.setMapTypeId(options.nameStyle);
}

			
			


/**
 * Recuperer l'objet gmap
 *
 * @return {GmapV3} Gmap Objet.
 */
Map.prototype.get = function(){	
	return this.map;
}

/**
 * Modifi l'objet GmapV3
 *
 * @param {GmapV3} Gmap Objet.
 */
Map.prototype.set = function (map) 
{
	 this.map = map;
}

/**
 * Test le chargement de la map
 *
 * @param {GmapV3} Gmap Objet.
 */
Map.prototype.isInit = function (map) 
{
        return this.map.getBounds() != null;
}

/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.moveTo = function(lat, lng) {
	this.map.panTo(new google.maps.LatLng(lat, lng));
}


/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.setCenter = function(lat, lng) {
	this.map.setCenter(new google.maps.LatLng(lat, lng));
}

/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.getCenter = function() {
	return this.map.getCenter();
}


/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.getNorthEast = function() {
	return this.map.getBounds().getNorthEast();
}

/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.getSouthWest = function() {
	return this.map.getBounds().getSouthWest();
}


/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.getZoom = function() {
	return this.map.getZoom();
}

/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.setZoom = function(zoom) {
	this.map.setZoom(zoom);
}
/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.setMapTypeId = function(type) {
	this.map.setMapTypeId(type);
}
/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.getMapTypeId = function(type) {
	this.map.getMapTypeId();
}
/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.panBy = function(x, y) {
	this.map.panBy(x, y);
}
/**
 * Methode redefiner de l'objet Gmap. (Voir la documentation de Google pour utilisation)
 */
Map.prototype.fitBounds = function(b) {
	this.map.fitBounds(b);
}


