google.load('maps', '2');
var gmap, gdir, gload, gform, gdepart;
var map, dir, gps, hover;
google.setOnLoadCallback(function(){
	gmap = $('gmap-acces');
	gdir = $('gdir-acces');
	gform = $('gform-acces');
	gdepart = $('acces-depart');
	gadresse = $('acces-adresse');
	garrivee = $('acces-arrivee');
	
	map = new google.maps.Map2(gmap);
	dir = new google.maps.Directions(map);
	gps = new GPS(4, true);
	
	gload = new Element('div').addClass('gload').setText('Chargement...').injectInside(gmap);
	
	var centre = new google.maps.LatLng(48.530248, -4.452209);

	map.setCenter(centre, 14);
	map.addControl(new google.maps.LargeMapControl());
	map.addControl(new google.maps.MapTypeControl());
	
	var marker = new google.maps.Marker(centre);
	map.addOverlay(marker);

	function itineraire(map, dir, list){
		marker.hide();
		list.empty();
		map.clearOverlays();
		
		hover = new GMarker(centre);
		map.addOverlay(hover);
		hover.hide();
		
		for(var i = 0; i < dir.getNumRoutes(); i++){
			var route = dir.getRoute(i);
			var geocode = route.getStartGeocode();
			var point = route.getStep(0).getLatLng();
			
			// Départ/arrêt
			new Element('a', {href: '#', title: 'Coordonnées GPS : '+gps.format(point.lat(), true)+', '+gps.format(point.lng(), false), events: {click: function(event){event = new Event(event).stop(); map.showMapBlowup(point)}}}).setHTML('<strong>'+((i == 0) ? 'Départ' : 'Arrêt')+' :</strong> '+geocode.address+' <em>'+route.getDistance().html+' (environ '+route.getDuration().html+')</em>').injectInside(new Element('li').addClass(((i == 0) ? 'depart' : 'pause')).injectInside(list));
			
			// Etapes
			var nbSteps = route.getNumSteps();
			for (var j = 0; j < nbSteps; j++){
				var step = route.getStep(j);
				var a = new Element('a', {href: '#', title: 'Coordonnées GPS : '+gps.format(step.getLatLng().lat(), true)+', '+gps.format(step.getLatLng().lng(), false)}).setHTML('<strong><span>Étape </span>'+(j+1)+' : </strong> '+step.getDescriptionHtml()+' <em>'+step.getDistance().html);
				a.step = step;
				a.addEvents({
					click: function(event){
						event = new Event(event).stop();
						map.showMapBlowup(this.step.getLatLng());
					},
					mouseenter: function(event){
						//map.panTo(this.step.getLatLng());
						hover.setPoint(this.step.getLatLng());
						hover.show();
					},
					mouseleave: function(event){
						hover.hide();
					}
				});
				var li = new Element('li').addClass('etape');
				if(j == 0) li.addClass('premiere');
				else if(j == nbSteps-1) li.addClass('derniere');
				a.injectInside(li.injectInside(list));
			}
		}
		
		// Arrivée
		new Element('a', {href: '#', title: 'Coordonnées GPS : '+gps.format(point.lat(), true)+', '+gps.format(point.lng(), false), events: {click: function(event){event = new Event(event).stop(); map.showMapBlowup(route.getEndLatLng())}}}).setHTML('<strong>Arrivée :</strong> '+route.getEndGeocode().address+'<em>Coordonnées GPS : '+gps.format(point.lat(), true)+', '+gps.format(point.lng(), false)+'</em>').injectInside(new Element('li').addClass('arrivee').injectInside(list));
	}
	
	GEvent.addListener(dir, 'load', function(){
		gload.setStyle('display', 'none');
		itineraire(map, dir, gdir);
	});

	GEvent.addListener(dir, 'error', function(){
		gload.setStyle('display', 'none');
		if(dir.getStatus().code == G_GEO_UNKNOWN_ADDRESS) var erreur = 'Aucune position géographique ne peut être trouvée pour une des adresses spécifiées. Ceci peut être du au fait que cette adresse est nouvelle, ou peut être incorrecte. Code de l\'erreur : '+dir.getStatus().code;
		else if(dir.getStatus().code == G_GEO_SERVER_ERROR) var erreur = 'Une requête de géolocalisation n\'a pas pu être exécutée. Code de l\'erreur : '+dir.getStatus().code;
		else if(dir.getStatus().code == G_GEO_MISSING_QUERY) var erreur = 'Vous devez entrer une adresse de départ. Code de l\'erreur : '+dir.getStatus().code;
		else if(dir.getStatus().code == G_GEO_BAD_KEY) var erreur = 'La licence est invalide, veuillez vérifier l\'intégrité de la clé. Code de l\'erreur : '+dir.getStatus().code;
		else if(dir.getStatus().code == G_GEO_BAD_REQUEST) var erreur = 'Une requête de n\'a pas pu être exécutée. Code de l\'erreur : '+dir.getStatus().code;
		else var erreur = 'Une erreur inconnue est survenue.';
		new Element('li').addClass('message chargement').setText(erreur).injectInside(gdir.empty());
	});
	GEvent.addListener(dir, 'addoverlay', function(){
		var startMarker = dir.getMarker(0);
		startMarker.hide();
		startMarker = new GMarker(startMarker.getPoint(), {draggable: true, icon: startMarker.getIcon()});
		map.addOverlay(startMarker);
		GEvent.addListener(startMarker, 'dragend', function(){
			var point = startMarker.getLatLng();
			gload.setStyle('display', 'block');
			new Element('p', {'class': 'message chargement'}).setText('Calcul de l\'itinéraire...').injectInside(gdir.empty());
			var from = gps.format(point.lat(), true)+', '+gps.format(point.lng(), false)+' @'+point.toUrlValue();
			gdepart.selectedIndex = gdepart.options.length-1;
			gadresse.getParent().setStyle('display', 'block');
			gadresse.value = from;
			dir.load('from: '+from+' to: '+garrivee.value, {getSteps: true, locale: 'fr'});
		});
		GEvent.addListener(startMarker, 'drag', function(){
			var point = startMarker.getLatLng();
			gdepart.selectedIndex = gdepart.options.length-1;
			gadresse.getParent().setStyle('display', 'block');
			gadresse.value = gps.format(point.lat(), true)+', '+gps.format(point.lng(), false)+' @'+point.toUrlValue();
		});
	});
	
	gform.addEvent('submit', function(event){
		event = new Event(event).stop();
		if(garrivee.value != '' && (gdepart.options[gdepart.selectedIndex].value != 'adresse' || (gdepart.options[gdepart.selectedIndex].value == 'adresse' && gadresse.value != ''))){
			gload.setStyle('display', 'block');
			//gmap.setStyle('display', 'block');
			gdir.setStyle('display', 'block');
			dir.load('from: '+(gdepart.options[gdepart.selectedIndex].value == 'adresse' ? gadresse.value : gdepart.options[gdepart.selectedIndex].value)+' to: '+garrivee.value, {getSteps: true, locale: 'fr'});
		}
	});
	if(garrivee.value != '' && (gdepart.options[gdepart.selectedIndex].value != 'adresse' || (gdepart.options[gdepart.selectedIndex].value == 'adresse' && gadresse.value != ''))){
		gload.setStyle('display', 'block');
		dir.load('from: '+(gdepart.options[gdepart.selectedIndex].value == 'adresse' ? gadresse.value : gdepart.options[gdepart.selectedIndex].value)+' to: '+garrivee.value, {getSteps: true, locale: 'fr'});
	}
	gdepart.addEvent('change', function(){
		if(gdepart.options[gdepart.selectedIndex].value == 'adresse') gadresse.getParent().setStyle('display', 'block');
		else gadresse.getParent().setStyle('display', 'none');
	});
	if(gdepart.options[gdepart.selectedIndex].value == 'adresse') gadresse.getParent().setStyle('display', 'block');
	else gadresse.getParent().setStyle('display', 'none');
	
	gload.setStyle('display', 'none');
	window.fireEvent('gmaploaded');
});

// Formatage des coordonnées GPS
var GPS = new Class({
	initialize: function(prec, card){
		if (prec) this.prec = prec;
		else this.prec = 0;
		if (card) this.card = true;
		else this.card = false; 
	},
	getCard: function(positive, lat) {
		if (lat) return positive ? "N" : "S";
		else return positive ? "E" : "O";
	},
	formatToDegMinSec : function(value, lat) {
		var prec = this.prec;
		var precMul = Math.pow(10, prec);
		var neg = value < 0 ? true : false;
		if (neg) value = -value;
		var degs = Math.floor(value);
		value -= degs;
		value *= 60;
		degs = degs.toString();
		if (neg && ! this.card) degs = "-"+degs;
		var mins = Math.floor(value);
		value -= mins;
		value *= 60;
		mins = mins.toString();
		var secs = value.toFixed(prec).toString();
		if (prec > 0) prec++;
		while(degs.length < 2) degs = "0" + degs;
		while(mins.length < 2) mins = "0" + mins;
		while(secs.length < 2 + prec) secs = " " + secs;
		return degs + '°' + mins + "'" + secs + '"' + (this.card ? this.getCard(!neg, lat) : "");
	},   
	formatToDegMin: function (value, lat) {
		var prec = this.prec;
		var precMul = Math.pow(10, prec);
		var neg = value < 0 ? true : false;
		if (neg) value = -value;
		var degs = Math.floor(value);
		value -= degs;
		value *= 60;
		degs = degs.toString();
		if (neg && ! this.card) degs = "-"+degs;
		var mins = value.toFixed(prec).toString();
		if (prec > 0) prec++;
		while(degs.length < 2) degs = "0" + degs;
		while(mins.length < 2 + prec) mins = "0" + mins;
		return degs + '°' + mins + "'" + (this.card ? this.getCard(!neg, lat) : "");
	},    
	formatToDec: function (value, lat) {
		var prec = this.prec;
		var precMul = Math.pow(10, prec);
		var neg = value < 0 ? true : false;
		if (neg) value = -value;
		var degs = value.toFixed(prec).toString();
		if (neg && ! this.card) degs = "-"+degs;
		if (prec > 0) prec++;
		while(degs.length < 3 + prec) degs = "0" + degs;
		return degs + '°' + (this.card ? this.getCard(!neg, lat) : "");
	}, 
	format: function(value, lat) {
		return this.formatToDegMin(value, lat);
	}
});
window.addEvent('unload', function(){
	google.maps.Unload();
});
