// JavaScript Document
/* Dependance -- Methode utilisee dans la classe --- */
Function.prototype.bind = function(){
	var __method = this, args = $.makeArray(arguments), object = args.shift();
  return function() {
  	return __method.apply(object, args.concat($.makeArray(arguments)));
  }
};

/* Classe gMap ----- */
/* ID container de la carte --- */
/* Coordonnees lat-lng du ou des points sur la carte : {lat: , lng: } ou [{lat: , lng: }, {lat: , lng: }, {lat: , lng: }] --- */
/* Options - overwrite les options par defaut --- */
function gMap(container, coords, options){
	this.options = {zoomLevel: 13, control: {display: true, type: 'small'}, defaultLat: 37, defaultLng: -122, draggable: false, rendered: true, gMapReady: function(){}};
	$.extend(this.options, options);
	this.container = $('#' + container);
	this.gMap = null; /* Instance de la google Map */
	this.gMarkers = new Array(); /* Tableau des markers GMarker */
	this.dragged = null; /* Instance du dernier GMarker deplacee */
	return this.initialize(coords);
};

gMap.prototype = {
	/* Initialize la carte */
	initialize: function(){
		try {
			if(!GBrowserIsCompatible()) return this;
		} catch(e) { alert('API Google n\'est pas accessible. Verifiez : l\'API Key & les inclusions des fichiers JS dependants.'); return this; }
		(arguments.length)? this.setPoints(arguments[0]) : this.setPoints([{lat: this.options.defaultLat, lng: this.options.defaultLng}])
		
		$(this).bind('gMapReady', function(e){
			this.onGMapReady(e);										 
		}.bind(this));		
		return this.renderMap();
	}, 
	
	/* Enregistre les coordonnees dans la propriete : gMarkers - Objets Google GMarker */
	setPoints: function(coords){
		this.gMarkers = ($.isArray(this.gMarkers))? this.gMarkers : new Array();
		var coords = ($.isArray(coords))? coords : [coords];
		for(var i = 0; i < coords.length; i++){
			var coord = coords[i];
			this.addPoint(new GLatLng(coord.lat, coord.lng));
		}
		return this;
	},
	
	/* Retrouve un point dans la propriete : gMarkers - Object GMarker */ 
	getPoint: function(gLatLng){
		var marker = null, gMarker = new GMarker(gLatLng);
		for(var i = 0; i < this.gMarkers.length; i++){
			if(gMarker.getLatLng() != this.gMarkers[i].getLatLng()) continue;
			else {
				marker = this.gMarkers[i];
				break;
			}	
		}
		return marker;
	}, 
	
	/* Ajoute un GMarker dans la propriete gMarkers + ajout un gestionnaire evenement dragend */
	addPoint: function(gLatLng){
		if(this.getPoint(gLatLng)) return;
		var options = (!this.options.draggable)? {} : {draggable: true};
		var gMarker = new GMarker(gLatLng, options);
		GEvent.addListener(gMarker, 'dragend', function(){
			this.dragged = arguments[0];
			$(this).trigger('dragend');
		}.bind(this, gMarker));
		this.gMarkers.push(gMarker);
		return this;		
	}, 
	
	/* Supprime un GMarker dans la propriete gMarkers */
	removePoint: function(gLatLng){
		if(!this.getPoint(gLatLng)) return;
		var gMarker = new GMarker(gLatLng), markers = new Array(), start = null;
		for(var i = 0; i < this.gMarkers.length; i++){
			if(gMarker.getLatLng() != this.gMarkers[i].getLatLng()) continue;
			else {
				start = i + 1;
				break;
			}
		}
		if(start) this.gMarkers.splice(start-1, 1);
		return this;		
	}, 
	
	/* Render de la carte avec les GMarkers enregistres */
	renderMap: function(){
		if(!this.options.rendered) return this;
		if(!this.gMap){
			this.gMap = new GMap2(document.getElementById(this.container.attr('id')));
			$(this.gMap.getContainer()).css({visibility: 'hidden'});
			GEvent.addListener(this.gMap, 'load', function(){
				$(this).trigger('gMapReady');			
			}.bind(this));
		}
		return this._renderMap();
	}, 
	
	_renderMap: function(){
		this.gMap.setCenter(this.getMapCenter(), this.getOptimalZoom());
		this.gMap.addControl(this.getControl());
		$(this.gMarkers).each(function(){
			var marker = arguments[1] || new GMarker(new GLatLng(this.options.defaultLat, this.options.defaultLng));
			this.gMap.addOverlay(marker);
		}.bind(this));
		return this;
	},
	
	/* Retourne le niveau de zoom optimum pour les GMarkers affiches sur la carte */
	getOptimalZoom: function(){
		var mapBounds = new GLatLngBounds(), markers = (arguments[0])? [arguments[0]] : this.gMarkers;
		for(var i = 0; i < markers.length; i++){
			var gLatLngObj = markers[i].getLatLng();
			mapBounds.extend(gLatLngObj);
		}
		var zoomLevel = this.gMap.getBoundsZoomLevel(mapBounds);
		return (markers.length && (zoomLevel < this.options.zoomLevel))? zoomLevel - 1 : this.options.zoomLevel;	
	},
	
	/* Retourne le centre de la carte en fonction des GMarkers affiches */
	getMapCenter: function(){
		var mapBounds = new GLatLngBounds(), markers = (arguments[0])? [arguments[0]] : this.gMarkers;
		for(var i = 0; i < markers.length; i++){
			var gLatLngObj = markers[i].getLatLng();
			mapBounds.extend(gLatLngObj);
		}
		return mapBounds.getCenter();		
	},
	
	/* Retourne le control Google map */
	getControl: function(){
		var control = new GSmallMapControl();
		switch(this.options.control.type){
			case '3D': 
				control = new GSmallZoomControl3D();
			break;
			case 'large3D':
				control = new GLargeMapControl3D();
			break;
			case 'large':
				control = new GLargeMapControl();
			break;
		}
		return control;
	}, 
	
	onGMapReady: function(e){
		this.options.gMapReady();	
	}
};
