/**
* Fichier	: geocoding.js
* Contenu	: Code javascript contenant les fonctions liées au geocoding
* Date		: 29/12/09
* @author	Gael Sauvanet
* @version	1.0
*/

var geocoder = null;		// objet de géocodage de google maps
var nbEtapes = 0;		// nombre d'étapes dans l'itinéraire
/**
 * Initialise l'outil de géocodage
 */
function initialiserGeocoder()
{
	// Initialisation de l'outil de géocodage de Google Maps
	geocoder = new google.maps.Geocoder();

	// Test autocompletion
	var totalBounds = new google.maps.LatLngBounds();
	var startPoint = new google.maps.LatLng(MIN_LAT, MIN_LON);
	var endPoint = new google.maps.LatLng(MAX_LAT, MAX_LON);

	totalBounds.extend(startPoint);
	totalBounds.extend(endPoint);

	$(function() {
	    $("#adresseDepart").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label: item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresse1($("#adresseDepart").val());
	      }
	    });
	});

	$(function() {
	    $("#adresseArrivee").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label:  item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresse2($("#adresseArrivee").val());
	      }
	    });
	});

	$(function() {
	    $("#adresseEtape1").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label:  item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresseEtape($("#adresseEtape1").val(),1);
	      }
	    });
	});

	$(function() {
	    $("#adresseEtape2").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label:  item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresseEtape($("#adresseEtape2").val(),2);
	      }
	    });
	});

	$(function() {
	    $("#adresseEtape3").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label:  item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresseEtape($("#adresseEtape3").val(),3);
	      }
	    });
	});
}

function initialiserGeocoder2()
{

	// Test autocompletion
	var totalBounds = new google.maps.LatLngBounds();
	var startPoint = new google.maps.LatLng(MIN_LAT, MIN_LON);
	var endPoint = new google.maps.LatLng(MAX_LAT, MAX_LON);

	totalBounds.extend(startPoint);
	totalBounds.extend(endPoint);

	$(function() {
	    $("#adresseEtape1").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label:  item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresseEtape($("#adresseEtape1").val(),1);
	      }
	    });
	});

	$(function() {
	    $("#adresseEtape2").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label:  item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresseEtape($("#adresseEtape2").val(),2);
	      }
	    });
	});

	$(function() {
	    $("#adresseEtape3").autocomplete({
	      //This bit uses the geocoder to fetch address values
	      source: function(request, response) {
		geocoder.geocode( {'region': 'FR', 'bounds':totalBounds , 'address': 'france, ' + ZONE_GEOCODING + ', ' + request.term}, function(results, status) {
		  response($.map(results, function(item) {
		    if((item.geometry.location.lat() <= MAX_LAT) && (item.geometry.location.lat() >= MIN_LAT) && (item.geometry.location.lng() <= MAX_LON) && (item.geometry.location.lng() >= MIN_LON))
		    return {
		      label:  item.formatted_address,
		      value: item.formatted_address
		    }
		  }));
		})
	      },
	      //This bit is executed upon selection of an address
	      select: function(event, ui) {
	      	voirAdresseEtape($("#adresseEtape3").val(),3);
	      }
	    });
	});
}


/**
 * Recherche l'adresse du point de départ
 */
function geocoderPositionDepart(lat,lon)
{

    if (geocoder) {
      var latlng = new google.maps.LatLng(lat, lon);
      geocoder.geocode({'latLng': latlng}, function(results, status) {

        if (status == google.maps.GeocoderStatus.OK) {

          if (results[0]) {
			
			var result = results[0].formatted_address;
			if(dynamic)
				document.getElementById("adresseDepart").value = result;
			else
			{
				e('adresse_depart').innerHTML = result;
			}

          }
        } else {
          alert("Geocoder failed due to: " + status);
        }
      });
    }
}

/**
 * Recherche l'adresse du point d'arrivée
 */
function geocoderPositionArrivee(lat,lon)
{

    if (geocoder) {
      var latlng = new google.maps.LatLng(lat, lon);
      geocoder.geocode({'latLng': latlng}, function(results, status) {

        if (status == google.maps.GeocoderStatus.OK) {

          if (results[0]) {
			var result = results[0].formatted_address;
			if(dynamic)
				document.getElementById("adresseArrivee").value = result;
			else
			{
				e('adresse_arrivee').innerHTML = result;
			}

          }
        } else {
          alert("Geocoder failed due to: " + status);
        }
      });
    }
}

/** Recherche l'adresse du point d'etape X ********************************* **/
function geocoderPositionEtape(lat,lon,numero)
{
    if (geocoder) {
      
      var latlng = new google.maps.LatLng(lat, lon);
      geocoder.geocode({'latLng': latlng}, function(results, status) {

        if (status == google.maps.GeocoderStatus.OK) {

          if (results[0]) {
			var result = results[0].formatted_address;
			if(dynamic)
			{
				document.getElementById("adresseEtape"+numero).value = result;
				document.getElementById("etape"+numero).className="draggable";
			}
			else
			{
				e('adresse_etape'+numero).value = result; // Stocké dans des champs cachés d'un formulaire pour static
			}
          }
        } else {
          alert("Geocoder failed due to: " + status);
        }
      });
    }
}

/**
 * Positionne le marqueur de départ à l'adresse indiquée
 * 
 * @param address l'adresse
 */
function voirAdresse1(address) {
	cacherURL();


	address = address.toLowerCase();
	if(address.indexOf(ZONE_GEOCODING) == -1)
		address += " " + ZONE_GEOCODING;

    if (geocoder) {
      geocoder.geocode( { 'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
 	place = results[0];


						// On récupère la position géographique du premier résultat
						point = place.geometry.location;

						// Supprimer les itinéraires						
						supprimerItineraires();

						// On lance la fonction xajax de sélection de noeud
						xajax_selectionnerNoeud(point.lng(),point.lat(),'depart');

						var nouvelleAdresse = "";

						nouvelleAdresse = place.formatted_address;
						
						document.getElementById("adresseDepart").value = nouvelleAdresse;


        } else {
          alert("Geocode was not successful for the following reason: " + status);
        }
      });
    }
}

/**
 * Positionne le marqueur d'arrivée à l'adresse indiquée
 * 
 * @param address l'adresse
 */
function voirAdresse2(address) {
	cacherURL();

	address = address.toLowerCase();
	if(address.indexOf(ZONE_GEOCODING) == -1)
		address += " " + ZONE_GEOCODING;

    if (geocoder) {
      geocoder.geocode( { 'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
 	place = results[0];


						// On récupère la position géographique du premier résultat
						point = place.geometry.location;

						// Supprimer les itinéraires						
						supprimerItineraires();

						// On lance la fonction xajax de sélection de noeud
						xajax_selectionnerNoeud(point.lng(),point.lat(),'arrivee');

						var nouvelleAdresse = "";

						nouvelleAdresse = place.formatted_address;
						
						document.getElementById("adresseArrivee").value = nouvelleAdresse;


        } else {
          alert("Geocode was not successful for the following reason: " + status);
        }
      });
    }
}

function voirAstuce()
{
	e('divastuce').style.display = 'block';
}

function cacherAstuce()
{
	e('divastuce').style.display = 'none'; 
}

// ***************************  MODIF ****************************************************************
/**
 * Calcul d'un itinéraire retour
 * 
 */
function itineraireRetour()
{
	// Inversion départ et arrivée
	arrivee=document.getElementById("adresseDepart").value; // ancienne valeur de départ
	depart=document.getElementById("adresseArrivee").value; // ancienne valeur d'arrivée
	nodetemp=nodeArrivee1; // Ancien noeud d'arrivée
	
	document.getElementById("adresseDepart").value=depart; // L'ancien arrivée devient le départ
	document.getElementById("adresseArrivee").value=arrivee; // L'ancien départ devient l'arrivée
	nodeArrivee1=nodeDepart1; // L'ancien noeud de départ devient le noeud d'arrivée
	nodeDepart1=nodetemp; // L'ancien noeud d'arrivée devient le noeud de départ


	lonlatD = new OpenLayers.LonLat(markerDepart.geometry.x,markerDepart.geometry.y); // Position de l'ancien marker de départ
	lonlatA = new OpenLayers.LonLat(markerArrivee.geometry.x,markerArrivee.geometry.y); // Position de l'ancien marker d'arrivée
	lattemp=lat1;
	lontemp=lon1;
	lat1=lat2;
	lon1=lon2;
	lat2=lattemp;
	lon2=lontemp;

	markerDepart.geometry.move((lonlatA.lon-lonlatD.lon),(lonlatA.lat-lonlatD.lat)); // La position de départ devient l'ancienne position d'arrivée
	markerArrivee.geometry.move((lonlatD.lon-lonlatA.lon),(lonlatD.lat-lonlatA.lat)); // La position d'arrivée devient l'ancienne position de départ
	layerMarkers.drawFeature(markerDepart); // On redessine le marker départ
	layerMarkers.drawFeature(markerArrivee); // On redessine le marker arrivée

	// Si il y a des étapes, il faut inverser leur ordre (ex:1 2 3 -> 3 2 1)
	if (ListeEtape!=null)
	{
		ListTempAddresse=Array(); // Buffer stockage ancienne adresses Etapes
		ListeTempEtape=Array(); // Buffer stockage ancien noeud Etapes
		ListeTempmarkerEtape=Array(); // Buffer stockage ancien marker Etapes

		// Pour la première moitié du tableau des étapes, on sauvegarde la première moitié et on la remplace pour la deuxieme moitié inversée
		for (i=1;i<=nbEtapes/2;i++) 
		{
			ListeTempmarkerEtape[i]=ListemarkerEtape[i]; // On stocke l'ancien marker i
			ListemarkerEtape[i]=ListemarkerEtape[nbEtapes+1-i]; // On place le marker (n-i) à la place du marker i
			ListemarkerEtape[i].attributes = 'etape'+(i); // L'étape (n-i) devient l'étape i

			ListeTempEtape[i]=ListeEtape[i]; // On stocke l'ancien noeud i
			ListeEtape[i]=ListeEtape[nbEtapes+1-i]; // On place le noeud (n-i) à la place du noeud i

			ListemarkerEtape[i].style = iconEtape[i];
			layerMarkers.addFeatures(ListemarkerEtape[i]);

			ListTempAddresse[i]=e("adresseEtape"+i).value; // On stocke l'ancienne adresse du noeud i
			e("adresseEtape"+i).value=e("adresseEtape"+(nbEtapes+1-i)).value; // On place l'adresse du noeud (n-i) à la place
		}

		// Pour la deuxieme moitié du tableau, on replace les noeuds, marker, adresses que l'on a sauvegardé précedemment
		for (i=parseInt((nbEtapes+1)/2)+1;i<=nbEtapes;i++) 
		{
			ListemarkerEtape[i]=ListeTempmarkerEtape[nbEtapes+1-i]; 
			ListemarkerEtape[i].attributes = 'etape'+(i);

			ListeEtape[i]=ListeTempEtape[nbEtapes+1-i];

			ListemarkerEtape[i].style = iconEtape[i];
			layerMarkers.addFeatures(ListemarkerEtape[i]);

			e("adresseEtape"+i).value=ListTempAddresse[nbEtapes+1-i];
		}
	}	


	// Calcul du nouvel itinéraire
	demandeServer(nodeDepart1,nodeArrivee1,ListeEtape);
}


/**
 * Ajout d'une étape dans l'interface (colonne de gauche)
 * 
 */
function ajouterEtape(num)
{
	if(num!=0 && dynamic)
	{
		e("etape"+num).style.display = 'block';
		nbEtapes+=1;
		return true;
	}
	else if (nbEtapes<NB_ETAPES_MAX) // On limite pour le moment le nombre d'étapes à 5
	{
		if (nbEtapes==0 || (dynamic && nbEtapes>0 && e("adresseEtape"+nbEtapes).value!=""))
		{		
			nbEtapes+=1;
			if (dynamic)
			{
				e("etape"+nbEtapes).style.display = 'block'; // on affiche un formulaire supplémentaire
				e("etape"+nbEtapes).className="vide";
				if (nbEtapes==NB_ETAPES_MAX) 
				{
					$("#myMenu").disableContextMenuItems('#etape');
					e("etapes_ajout1").style.display ='none';
					e("etapes_ajout2").style.display ='none';
				}
			}
		}
		return true;
	}
	else
		return false;
}


/**
 * Interversion de deux étapes. Utilisé pour le drag and drop des étapes
 * 
 * @param i Le numéro de l'étape que l'on déplace
 * @param j Le numéro de l'étape que l'on va remonter ou descendre pour laisser la place à i
 */
function switchEtape(i,j)
{
	 
	EtapeTemp=ListeEtape[i]; // Buffer contenant l'étape i
	markerEtapeTemp=ListemarkerEtape[i]; // Buffer contenant le marker de i

	ListemarkerEtape[i].style = iconEtape[j];
	ListemarkerEtape[j].style = iconEtape[i];
	layerMarkers.addFeatures(ListemarkerEtape[i]);
	layerMarkers.addFeatures(ListemarkerEtape[j]);

	// Switch des étapes
	ListeEtape[i]=ListeEtape[j];
	ListeEtape[j]=EtapeTemp;

	// Switch des markers
	ListemarkerEtape[i]=ListemarkerEtape[j];
	ListemarkerEtape[i].attributes='etape'+(i);
	ListemarkerEtape[j]=markerEtapeTemp;
	ListemarkerEtape[j].attributes='etape'+(j);	

	// Switch des blocs dans l'interface. (ex: on avait bloc1, bloc2. On a bloc2,bloc1)

	// On remet les ID dans l'ordre
	e("etape"+j).id="etapetemp"; // On retire l'ID du block contenant l'étape j dans l'interface
	e("etape"+i).id="etape"+j; // Comme il n'existe plus de bloc ayant l'ID "etapej", on peut donner ce nom au block contenant l'adresse de i
	e("etapetemp").id="etape"+i; // Comme il n'existe plus de bloc "etapei", on l'affecte au bloc contenant l'adresse de j
	
	// Sauvegarde des adresses
	Adresse1=e("adresseEtape"+i).value; // On sauvegarde l'adresse de i
	Adresse2=e("adresseEtape"+j).value; // On sauvegarde l'adresse de j

	// Le bloc2 est devenu bloc1 mais il contient toujours des name ou des fonctions du type "validerEtape2".
	// On lui donne le contenu de l'ancien bloc1
	temp=e("etape"+j).innerHTML; // On sauvegarde le contenant du bloc "etapej" qui a cet instant contient les infos de l'ancien bloc "etapei"
	e("etape"+j).innerHTML=e("etape"+i).innerHTML; // On lui affecte les infos de l'ancien bloc "etapej"
	e("etape"+i).innerHTML=temp; // On affecte au nouveau bloc "etapei" les informations de l'ancien bloc "etapei"

	// On réaffecte les valeurs du champs adresse qui est perdu avec l'utilisation de innerHTML
	e("adresseEtape"+i).value=Adresse2; 
	e("adresseEtape"+j).value=Adresse1;

	initialiserGeocoder2();
}



/**
 * Suppression d'une étape dans l'interface	
 * @param num le numéro de l'étape à supprimer
 */
function supprimerEtape(num)
{
	if (nbEtapes==NB_ETAPES_MAX)
	{
		$("#myMenu").enableContextMenuItems('#etape');
		e("etapes_ajout1").style.display ='block';
		e("etapes_ajout2").style.display ='block';
	}

	e("etape"+nbEtapes).style.display = 'none'; // On cache le bloc de l'étape
	e("etape"+nbEtapes).className="";

	// Si ce n'est pas la dernière étape qu'on supprime, on shift toutes les étapes suivantes d'un cran vers la gauche (ex: etape3 -> etape2)
	if (num!=nbEtapes)
		for (i=num;i<nbEtapes;i++)
		{
			e("adresseEtape"+i).value=e("adresseEtape"+(i+1)).value;
			ListemarkerEtape[i+1].attributes = 'etape'+(i);
			ListemarkerEtape[i+1].style = iconEtape[i];
			layerMarkers.addFeatures(ListemarkerEtape[i+1]);
		}

	// On supprime de l'interface une étape et on efface la rue concernée
	e("adresseEtape"+nbEtapes).value="";
	nbEtapes-=1;


	// la fonction splice permet de supprimer un élément d'une liste (ou une sous-liste d'une liste) puis compacte la liste résultat
	ListeEtape.splice(num,1); // Suppression du noeud étape X
	layerMarkers.removeFeatures(ListemarkerEtape[num]); // Suppression du marker étape X sur le calque
	ListemarkerEtape.splice(num,1); // Suppression du marker étape X dans la liste des markers

	demandeServer(nodeDepart1,nodeArrivee1,ListeEtape) // On calcul le nouvel itinéraire
}

/**
 * Positionne un marqueur sur une étape à l'adresse indiquée
 * 
 * @param address l'adresse
 * @param numEtape le numéro de l'étape
 */
function voirAdresseEtape(address,numEtape) {

	cacherURL();

	address = address.toLowerCase();
	if(address.indexOf(ZONE_GEOCODING) == -1)
		address += " " + ZONE_GEOCODING;

	if (geocoder) {
		geocoder.geocode( { 'address': address}, function(results, status) {
			if (status == google.maps.GeocoderStatus.OK) {
				place = results[0];

				// On récupère la position géographique du premier résultat
				point = place.geometry.location;

				// Supprimer les itinéraires						
				supprimerItineraires();
				// On lance la fonction xajax de sélection de noeud
				xajax_selectionnerNoeud(point.lng(),point.lat(),'etape',numEtape);
				var nouvelleAdresse = "";
				nouvelleAdresse = place.formatted_address;
				document.getElementById("adresseEtape"+numEtape).value = nouvelleAdresse;
//				document.getElementById("etape"+numEtape).className="draggable";
			} else {
          			alert("Geocode was not successful for the following reason: " + status);
        		}
      		});
    	}
}


