var gis = null ; /// Point d'entrée pour toutes les fonctions du SIG
var mapParent = '' ;

/// Internationalisation
var I18N = new Object() ;
I18N.newRoute = new Object() ;
I18N.newRoute["FR"] = "Nouvel itin&eacute;raire" ;
I18N.newRoute["EN"] = "New route" ;
I18N.print = new Object() ;
I18N.print["FR"] = "Imprimer" ;
I18N.print["EN"] = "Print" ;
I18N.userLoc = new Object() ;
I18N.userLoc["FR"] = "&Eacute;tape utilisateur" ;
I18N.userLoc["EN"] = "User location" ;
I18N.searchLoc = new Object() ;
I18N.searchLoc["FR"] = "Recherche de lieux avec Google" ;
I18N.searchLoc["EN"] = "Location search" ;
I18N.searchArea = new Object() ;
I18N.searchArea["FR"] = "Ville, adresse ou coordonn&eacute;es" ;
I18N.searchArea["EN"] = "City, address or coordinates" ;
I18N.mustConnect = new Object() ;
I18N.mustConnect["FR"] = "Vous devez vous connecter pour pouvoir sauvegarder\nVotre itin&eacute;raire ne sera pas perdu tant que vous ne fermerez pas votre navigateur" ;
I18N.mustConnect["EN"] = "You must be logged on in order to save\nYour route will not be lost until you close your browser" ;
I18N.nameRoute = new Object() ;
I18N.nameRoute["FR"] = "Donner un nom &agrave; votre itin&eacute;raire" ;
I18N.nameRoute["EN"] = "Give your route a name" ;
I18N.routeSaved = new Object() ;
I18N.routeSaved["FR"] = "Votre itin&eacute;raire a bien &eacute;t&eacute; sauvegard&eacute;" ;
I18N.routeSaved["EN"] = "Your route has been successfully saved" ;
I18N.moreLoc = new Object() ;
I18N.moreLoc["FR"] = "En savoir plus" ;
I18N.moreLoc["EN"] = "More about this location" ;
I18N.addLoc = new Object() ;
I18N.addLoc["FR"] = "Ajouter l&#039;&eacute;tape" ;
I18N.addLoc["EN"] = "Add this location" ;
I18N.delLoc = new Object() ;
I18N.delLoc["FR"] = "Supprimer l&#039;&eacute;tape" ;
I18N.delLoc["EN"] = "Remove this location" ;
I18N.locLimit = new Object() ;
I18N.locLimit["FR"] = "25 &eacute;pages maximum" ;
I18N.locLimit["EN"] = "Maximum 25 locations" ;
I18N.start = new Object() ;
I18N.start["FR"] = "D&eacute;part" ;
I18N.start["EN"] = "Start" ;
I18N.stop = new Object() ;
I18N.stop["FR"] = "Arriv&eacute;e" ;
I18N.stop["EN"] = "Arrival" ;
I18N.up = new Object() ;
I18N.up["FR"] = "Monter" ;
I18N.up["EN"] = "Move up" ;
I18N.down = new Object() ;
I18N.down["FR"] = "Descendre" ;
I18N.down["EN"] = "Move down" ;
I18N.del = new Object() ;
I18N.del["FR"] = "Supprimer" ;
I18N.del["EN"] = "Remove" ;
I18N.noResult = new Object() ;
I18N.noResult["FR"] = "Aucun r&eacute;sultat" ;
I18N.noResult["EN"] = "No result" ;
I18N.waitText = new Object() ;
I18N.waitText["FR"] = "Recherche en cours, patientez ..." ;
I18N.waitText["EN"] = "Searching, please wait ..." ;
I18N.result = new Object() ;
I18N.result["FR"] = "R&eacute;sultats " ;
I18N.result["EN"] = "Results " ;
I18N.ofAbout = new Object() ;
I18N.ofAbout["FR"] = " sur un total de " ;
I18N.ofAbout["EN"] = " of about " ;

/**
 * Initialise le SIG
 * mapID : l'id de l'élément destiné à accueillir la carte
 * locsID : l'id de l'élément destiné à accueillir la liste des étapes
 * directionsID : l'id de l'élément destiné à accueillir la feuille de route
 * allowMod : permettre les modifications ?
 * routeID : id route pour modification
 * lg : code langue
 * path : chemin fichier
 * walk : non routier
 */
init = function(mapID, locsID, directionsID, allowMod, auth, routeID, lg, path, walk) {
	gis = new GIS(mapID, locsID, directionsID, allowMod, auth, routeID, lg, path, walk) ;
}

/**
 * Déplace et affiche/cache la carte
 * mapID : l'id de l'élément destiné à accueillir la carte
 * parentID : le nouveau parent de la carte
 */
moveMap = function(mapID, parentID, routeID, path, walk) {
	if (!mapParent || mapParent.length == 0) showMap(mapID, parentID, routeID, path, walk) ;
	else if (mapParent == parentID) {
		processCollapseOnHeight(parentID) ;
		mapParent = '' ;
	} else {
		processCollapseOnHeight(mapParent) ;
		setTimeout("showMap('"+mapID+"', '"+parentID+"', "+routeID+", '"+path+"', "+walk+")", 2000) ;
	}
}

/**
 * Affiche la carte dans le parent choisi
 * mapID : l'id de l'élément destiné à accueillir la carte
 * parentID : le nouveau parent de la carte
 */
showMap = function(mapID, parentID, routeID, path, walk) {
	var map = document.getElementById(mapID) ;
	var parent = document.getElementById(parentID) ;
	if (map.parentNode != parent) parent.appendChild(map) ;
	map.style.display = 'block' ;
	if (gis.trace) gis.openLayersMap.removeLayer(gis.trace) ;
	gis.walk = walk ;
	gis.trace = null ;
	gis.googleDirection.clear() ;
	gis.googleSatDirection.clear() ;
	gis.googlePhyDirection.clear() ;
	gis.route.googleDirection.clear() ;
	if (path && path.length > 0) {
		gis.useGoogle = false ;
		gis.path = path ;
		gis.trace = new OpenLayers.Layer.WMS('Trace Layer','http://vtn.actimage-ext.net/cgi-bin/mapserv?map='+gis.path, {layers: ['route'], transparent: 'true', reproject: 'true'}, {projection: 'epsg:900913', isBaseLayer: false}) ;
		gis.openLayersMap.addLayer(gis.trace) ;
		gis.trace.setZIndex(320) ;
	} else {
		gis.useGoogle = true ;
	}
	gis.loadRoute(routeID) ;
	processExpandOnHeight(parentID) ;
	mapParent = parentID ;
}

/**
 * Parse un texte en XML
 * text : le texte à parser
 */
parseResponseText = function(text) {
	var xmlDoc ;
	try
	{
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM") ;
		xmlDoc.async = "false" ;
		xmlDoc.loadXML(text) ;
	} catch (e) {
		var parser = new DOMParser() ;
		xmlDoc = parser.parseFromString(text,"text/xml") ;
	}
	return xmlDoc ;
}

/**
 * Coche toutes les checkboxes ayant un nom particulier
 * checkboxesName : le nom des checkboxes à cocher
 */
checkAll = function(checkboxesName) {
	var checkboxes = document.getElementsByName(checkboxesName) ;
	for (var i = 0 ; i < checkboxes.length ; ++i) {
		checkboxes[i].checked = true ;
	}
}

/**
 * Décoche toutes les checkboxes ayant un nom particulier
 * checkboxesName : le nom des checkboxes à décocher
 */
uncheckAll = function(checkboxesName) {
	var checkboxes = document.getElementsByName(checkboxesName) ;
	for (var i = 0 ; i < checkboxes.length ; ++i) {
		checkboxes[i].checked = false ;
	}
}

clearMarkers = function(evt) {
	var total = this.getNumGeocodes() ;
	for (var i = 0 ; i < total ; ++i) {
		this.getMarker(i).hide() ;
	}
}

/**
 * Classe principale du SIG
 * mapID : l'id de l'élément destiné à accueillir la carte
 * locsID : l'id de l'élément destiné à accueillir la liste des étapes
 * directionsID : l'id de l'élément destiné à accueillir la feuille de route
 * allowMod : modifications permises ?
 * routeID : id route pour modification
 * lg : code langue
 * path : chemin fichier
 * walk : non routier ?
 */
function GIS(mapID, locsID, directionsID, allowMod, auth, routeID, lg, path, walk) {

	/// Utilisation de Google ?
	if (path.length > 0 && allowMod) {
		this.useGoogle = false ;
		this.path = path ;
	} else this.useGoogle = true ;

	/// Langue
	this.lg = lg ;

	/// Non routier ?
	this.walk = walk ;

	/// Modifications permises ?
	this.allowMod = allowMod ;

	var controls = [new OpenLayers.Control.PanZoomBar(), new OpenLayers.Control.Navigation()] ;

	/// La carte OpenLayers
	this.openLayersMap = new OpenLayers.Map(mapID, {
		projection: new OpenLayers.Projection("EPSG:900913"),
		displayProjection: new OpenLayers.Projection("EPSG:4326"),
		units: "meters",
		numZoomLevels: 19,
		maxExtent: new OpenLayers.Bounds(-572551.5602902, 5066251.6085148, 916595.81888266, 6687080.8781479),
		maxResolution: 156543,
		controls: controls
	}) ;

	/// Le layer des vecteurs
	this.vectorLayer = new OpenLayers.Layer.Vector("Vectors") ;
	/// Le layer pour le rayon de recherche
	this.radiusLayer = new OpenLayers.Layer.Vector("Search radius") ;

	/// Layers Google
	this.googleLayer = new OpenLayers.Layer.Google("Google Plan", {"sphericalMercator":true, minZoomLevel: 5, maxZoomLevel: 18}) ;
	this.googleSatLayer = new OpenLayers.Layer.Google("Google Sat", {type:G_HYBRID_MAP, "sphericalMercator":true, minZoomLevel: 5, maxZoomLevel: 18}) ;
	this.googlePhyLayer = new OpenLayers.Layer.Google("Google Phy", {type:G_PHYSICAL_MAP, "sphericalMercator":true, minZoomLevel: 5, maxZoomLevel: 18}) ;

	/// L'itinéraire
	this.route = new Route(locsID, directionsID) ;
	/// Un tableau associatif <id, location>
	this.locationsHash = new Array() ;
	/// La popup actuellement ouverte
	this.openedPopup = null ;

	/// Les features sur itinéraire
	this.onFeatures = new Array() ;
	/// Les features hors itinéraire
	this.outFeatures = new Array() ;

	/// ID généré
	this.idBase = 0 ;
	///
	this.auth = (auth == 'true') ? true : false ;
	///
	this.routeID = routeID ;
	///
	this.name = document.createElement("span");
	this.name.innerHTML = I18N.newRoute[this.lg] ;

	/// Ajout des layers à la carte
	this.openLayersMap.addLayer(this.googleLayer) ;
	this.openLayersMap.addLayer(this.googleSatLayer) ;
	this.openLayersMap.addLayer(this.googlePhyLayer) ;
	this.openLayersMap.addLayer(this.radiusLayer) ;
	this.openLayersMap.addLayer(this.vectorLayer) ;

	/// L'objet GoogleMaps
	this.googleMap = this.googleLayer.mapObject ;
	this.googleSatMap = this.googleSatLayer.mapObject ;
	this.googlePhyMap = this.googlePhyLayer.mapObject ;
	if (this.useGoogle) {
		var feinte = document.createElement("div") ;

		/// Le calculateur d'itinéraire GoogleMaps
		this.googleDirection = new GDirections(this.googleMap, feinte) ;
		this.googleSatDirection = new GDirections(this.googleSatMap, feinte) ;
		this.googlePhyDirection = new GDirections(this.googlePhyMap, feinte) ;

		GEvent.addListener(this.googleDirection, 'addoverlay', clearMarkers) ;
		GEvent.addListener(this.googleSatDirection, 'addoverlay', clearMarkers) ;
		GEvent.addListener(this.googlePhyDirection, 'addoverlay', clearMarkers) ;
	}
	/// Le moteur de recherche de lieux Google
	this.googleSearch = new google.search.LocalSearch() ;
	/// Après terminaison de la recherche, créer marqueurs pour les résultats
	this.googleSearch.setSearchCompleteCallback(this, this.drawSearchResult) ;
	/// 8 résultats par recherche
	this.googleSearch.setResultSetSize(google.search.Search.LARGE_RESULTSET) ;

	if (this.allowMod) {
		/// Contrôle pour le drag & drop
		var drag = new OpenLayers.Control.DragFeature(this.vectorLayer) ;
		drag.onComplete = function(evt) {
			OpenLayers.Event.stop(evt) ;
			var lonlat = new OpenLayers.LonLat(evt.geometry.x, evt.geometry.y) ;
			var oldLoc = evt.location ;
			evt.location = new Location("user"+(gis.idBase++), lonlat, oldLoc.routePosition, I18N.userLoc[gis.lg], "", 0) ;
			evt.location.feature = evt ;
			evt.location.removeMarker() ;
			if (oldLoc.routePosition >= 0) {
				gis.route.locations[oldLoc.routePosition] = evt.location ;
				evt.location.createUpdateFeature() ;
				setTimeout("gis.route.redrawRoute()", 1000) ;
			} else {
				evt.location.createUpdateFeature() ;
			}
			oldLoc.routePosition = -1 ;
			oldLoc.removeMarker();
		};
		this.openLayersMap.addControl(drag);
		drag.activate();
	}

	/// Contrôle pour le clic sur marqueurs
	var onClick = function(evt) {gis.openClosePopup(evt.popup) ; OpenLayers.Event.stop(evt) ;};
	var select = new OpenLayers.Control.SelectFeature(
					this.vectorLayer,
					{
						clickout: false, toggle: false,
						multiple: false, hover: false,
						box: false,
						callbacks: {click: onClick}
					}
				);
	this.openLayersMap.addControl(select);
	select.activate();

	if (this.path) {
		/// Layer Trace
		this.trace = new OpenLayers.Layer.WMS('Trace Layer','http://vtn.actimage-ext.net/cgi-bin/mapserv?map='+this.path, {layers: ['route'], transparent: 'true', reproject: 'true'}, {projection: 'epsg:900913', isBaseLayer: false});
		this.openLayersMap.addLayer(this.trace);
		this.trace.setZIndex(320) ;
	}

	/// Layer pour affichage itinéraire BD Carto
	this.routeLayer = null ;

	/// Centrage initial
	this.openLayersMap.zoomToMaxExtent() ;
}

/**
 * Change le base layer courant
 * layerName : nom du nouveau base layer
 */
GIS.prototype.switchToLayer = function(layerName) {
	var layer = null ;
	switch (layerName) {
		case "sat" :
			layer = this.googleSatLayer ;
			break ;
		case "plan" :
			layer = this.googleLayer ;
			break ;
		case "physical" :
			layer = this.googlePhyLayer ;
			break ;
		case "wms" :
			layer = this.wms ;
			break ;
		default : ;
	}
	if (layer != null) this.openLayersMap.setBaseLayer(layer) ;
}

/**
 * Créé un lieu pour chaque résultat de la recherche
 */
GIS.prototype.drawSearchResult = function() {
	this.vectorLayer.removeFeatures(gis.outFeatures) ;
	this.outFeatures = new Array() ;
	var minlon = 25000000 ;
	var minlat = 25000000 ;
	var maxlon = -25000000 ;
	var maxlat = -25000000 ;
	for (var i = 0 ; i < this.googleSearch.results.length ; ++i) {
		var result = this.googleSearch.results[i] ;
		var lonlat = new OpenLayers.LonLat(result.lng, result.lat);
		lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
		if (lonlat.lon < minlon) minlon = lonlat.lon ;
		if (lonlat.lat < minlat) minlat = lonlat.lat ;
		if (lonlat.lon > maxlon) maxlon = lonlat.lon ;
		if (lonlat.lat > maxlat) maxlat = lonlat.lat ;
		var loc = new Location("user"+(this.idBase++), lonlat, -1, result.titleNoFormatting, '', 0) ;
		loc.createUpdateFeature() ;
	}
	this.openLayersMap.zoomToExtent(new OpenLayers.Bounds(minlon, minlat, maxlon, maxlat)) ;
}

/**
 * Effectue une recherche de lieux avec Google
 * queryFieldId : l'id du champ où la requête doit être tapée
 */
GIS.prototype.searchGoogle = function() {
	var text = document.createElement("span") ;
	text.innerHTML = I18N.searchLoc[this.lg] ;
	var query = text.innerHTML ;
	text.innerHTML = I18N.searchArea[this.lg] ;
	query = prompt(query, text.innerHTML) ;
	if (query && query.length > 0) {
		this.googleSearch.clearResults() ;
		this.googleSearch.setCenterPoint(this.googleMap.getCenter()) ;
		this.googleSearch.execute(query) ;
	}
}

/**
 * Ouvre ou ferme une popup
 * popup : la popup à ouvrir/fermer
 */
GIS.prototype.openClosePopup = function(popup) {
	if (popup == null) {
		this.openedPopup.hide() ;
		this.openedPopup = null ;
	} else if (this.openedPopup == popup) {
		popup.hide() ;
		this.openedPopup = null ;
	} else if (this.openedPopup != null) {
		this.openedPopup.hide() ;
		popup.show() ;
		this.openedPopup = popup ;
	} else {
		popup.show() ;
		this.openedPopup = popup ;
	}
}

/**
 * Créer un pentacontagone régulier
 * lon : la longitude du centre
 * lat : la latitude du centre
 * radius : le rayon du pentacontagone
 */
GIS.prototype.drawCircle = function(lon, lat, radius) {
	var vector = new OpenLayers.Feature.Vector(OpenLayers.Geometry.Polygon.createRegularPolygon(
		new OpenLayers.Geometry.Point(lon, lat), radius, 50, 0
	)) ;
	this.radiusLayer.addFeatures(new Array(vector));
	this.openLayersMap.zoomToExtent(new OpenLayers.Bounds(lon-radius, lat-radius, lon+radius, lat+radius)) ;
}

/**
 * Charge un itinéraire
 * routeID : l'ID de l'itinéraire à charger
 * isUser : itinéraire utilisateur ou prédéfini
 * Si routeID = -1, l'itinéraire actuel est chargé
 */
GIS.prototype.loadRoute = function(routeID) {
	var req = createAjaxHTTPREQUEST() ;
	req.onreadystatechange = function() {
		if (req.readyState == 4 && req.status == 200) {
			var result = parseResponseText(req.responseText).documentElement ;
			var locations = result.getElementsByTagName("location") ;
			var size = result.getElementsByTagName("size")[0].firstChild.nodeValue ;
			if (result.getElementsByTagName("name")[0].firstChild)
				gis.name.innerHTML = result.getElementsByTagName("name")[0].firstChild.nodeValue ;
			var minlonlat = new OpenLayers.LonLat(result.getElementsByTagName("minlon")[0].firstChild.nodeValue, 
				result.getElementsByTagName("minlat")[0].firstChild.nodeValue) ;
			var maxlonlat = new OpenLayers.LonLat(result.getElementsByTagName("maxlon")[0].firstChild.nodeValue, 
				result.getElementsByTagName("maxlat")[0].firstChild.nodeValue) ;
			minlonlat = minlonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
			maxlonlat = maxlonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
			gis.openLayersMap.zoomToExtent(new OpenLayers.Bounds(minlonlat.lon, minlonlat.lat, maxlonlat.lon, maxlonlat.lat)) ;
			var locsArray = new Array() ;
			for (var i = 0 ; i < locations.length ; ++i) {
				var location = locations[i] ;
				var id = location.getElementsByTagName("id")[0].firstChild.nodeValue ;
				var position = location.getElementsByTagName("position")[0].firstChild.nodeValue ;
				var lonlat = new OpenLayers.LonLat(location.getElementsByTagName("longitude")[0].firstChild.nodeValue,
								location.getElementsByTagName("latitude")[0].firstChild.nodeValue) ;
				lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
				if (gis.locationsHash[id]) locsArray[position] = gis.locationsHash[id] ;
				else locsArray[position] = new Location(id, lonlat, position,
								(location.getElementsByTagName("title")[0].firstChild)?location.getElementsByTagName("title")[0].firstChild.nodeValue:'',
							(location.getElementsByTagName("description")[0].firstChild)?location.getElementsByTagName("description")[0].firstChild.nodeValue:'', 1) ;
			}
			gis.route.clear() ;
			gis.route.addLocations(locsArray) ;
		}
	}
	req.open("post","actions_ajax.php",true) ;
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded') ;
	req.send("action=loadRoute&route_id="+routeID) ;
}

/**
 * Charge un lieu
 * locationID : l'ID du lieu à charger
 */
GIS.prototype.loadLocation = function(locationID) {
	var req = createAjaxHTTPREQUEST() ;
	req.onreadystatechange = function() {
		if (req.readyState == 4 && req.status == 200) {
			var result = parseResponseText(req.responseText).documentElement ;
			var location = result.firstChild ;
			if (location != null) {
				var lonlat = new OpenLayers.LonLat(location.getElementsByTagName("longitude")[0].firstChild.nodeValue,
									location.getElementsByTagName("latitude")[0].firstChild.nodeValue) ;
				lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
				var id = location.getElementsByTagName("id")[0].firstChild.nodeValue ;
				if (!gis.locationsHash[id]) {
					var loc = new Location(id, lonlat, -1,
							location.getElementsByTagName("title")[0].firstChild.nodeValue,
							location.getElementsByTagName("description")[0].firstChild.nodeValue, 1) ;
					loc.createUpdateFeature() ;
				} else gis.locationsHash[id].createUpdateFeature() ;
			}
		}
	}
	req.open("post","actions_ajax.php",true) ;
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded') ;
	req.send("action=loadLocation&location_id="+locationID) ;
}

/**
 * Recherche des lieux dans la base de données
 */
GIS.prototype.searchDatabase = function(group) {

	var text = document.getElementById("waitText") ;
	text.style.color = "red" ;
	text.innerHTML = I18N.waitText[this.lg] ;

	this.clearSearchResult();
	var req = createAjaxHTTPREQUEST() ;
	req.onreadystatechange = function() {
		if (req.readyState == 4 && req.status == 200) {
			var result = parseResponseText(req.responseText).documentElement ;
			var locations = result.getElementsByTagName("location") ;
			var total = parseInt(result.getElementsByTagName("total")[0].firstChild.nodeValue) ;
			var offset = parseInt(result.getElementsByTagName("offset")[0].firstChild.nodeValue) ;
			var count = parseInt(result.getElementsByTagName("count")[0].firstChild.nodeValue) ;
			offset++ ;
			count = offset + count - 1 ;
			if (result.getElementsByTagName("distance")[0].firstChild != null && 
				result.getElementsByTagName("proximitylat")[0].firstChild != null && 
				result.getElementsByTagName("proximitylon")[0].firstChild != null) {
				var distance = result.getElementsByTagName("distance")[0].firstChild.nodeValue ;
				var plonlat = new OpenLayers.LonLat(result.getElementsByTagName("proximitylon")[0].firstChild.nodeValue,
												result.getElementsByTagName("proximitylat")[0].firstChild.nodeValue) ;
				plonlat = plonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
				gis.drawCircle(plonlat.lon, plonlat.lat, distance*1000) ;
			}
			if (locations.length == 0) {
				var text = document.createElement("span") ;
				text.innerHTML = I18N.noResult[gis.lg] ;
				alert(text.innerHTML) ;
			} else {
				for (var i = 0 ; i < locations.length ; ++i) {
					var location = locations[i] ;
					var lonlat = new OpenLayers.LonLat(location.getElementsByTagName("longitude")[0].firstChild.nodeValue,
									location.getElementsByTagName("latitude")[0].firstChild.nodeValue) ;
					lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
					var id = location.getElementsByTagName("id")[0].firstChild.nodeValue ;
					var genre = location.getElementsByTagName("genre")[0].firstChild.nodeValue ;
					if (!gis.locationsHash[id]) {
						var loc = new Location(id, lonlat, -1,
								(location.getElementsByTagName("title")[0].firstChild)?location.getElementsByTagName("title")[0].firstChild.nodeValue:'',
								(location.getElementsByTagName("description")[0].firstChild)?location.getElementsByTagName("description")[0].firstChild.nodeValue:'',
								genre) ;
						loc.createUpdateFeature() ;
					} else gis.locationsHash[id].createUpdateFeature() ;
				}
			}
			var text = document.getElementById("waitText") ;
			text.style.color = "green" ;
			text.innerHTML = "("+I18N.result[gis.lg]+offset+"-"+count+I18N.ofAbout[gis.lg]+total+")" ;
		}
	}
	var params = '&btn='+group ;
	var div = document.getElementById("div"+group) ;
	var keywords = document.getElementById(group+"_keywords").value ;
	var proximity = document.getElementById(group+"_proximity").value ;
	var distance = document.getElementById(group+"_distance").value ;

	var inputs = div.getElementsByTagName("input") ;

	var catArray = new Array() ;
	var typArray = new Array() ;
	var criArray = new Array() ;

	for (var i = 0 ; i < inputs.length ; ++i) {
		if (inputs[i].id == "from") params += "&from="+inputs[i].value ;
		else if (inputs[i].id == "to") params += "&to="+inputs[i].value ;
		else if (inputs[i].checked)
			if (inputs[i].id.match("categorieTheme")) catArray.push(inputs[i].id.slice(14)) ;
			else if (inputs[i].id.match("typeTheme")) typArray.push(inputs[i].id.slice(9)) ;
			else if (inputs[i].id.match("critere")) criArray.push(inputs[i].id.slice(7)) ;
	}
	params += '&cat='+catArray.toString() ;
	params += '&typ='+typArray.toString() ;
	params += '&cri='+criArray.toString() ;

	params += '&kw='+urlencode(keywords)+'&prox='+proximity+'&dist='+distance ;

	if (document.getElementById("page")) params += '&page='+document.getElementById('page').value ;

	req.open("post","actions_ajax.php",true) ;
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded') ;
	req.send("action=searchLocations"+params) ;
}

/**
 * Sauvegarde l'itinéraire comme itinéraire actuel
 */
GIS.prototype.saveInSession = function() {
	var locations = '' ;
	for (var i = 0 ; i < this.route.locations.length ; ++i) {
		var location = this.route.locations[i] ;
		if (location.id.charAt(0) != "u") {
			locations += location.id+',' ;
		} else {
			var lonlat = location.lonlat.clone() ;
			lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")) ;
			locations += lonlat.lon+'|'+lonlat.lat+'|'+urlencode(location.title)+',' ;
		}
	}
	if (locations.length > 0) locations = locations.substring(0, locations.length - 1) ;
	var req = createAjaxHTTPREQUEST() ;
	var w = (this.walk)?1:0 ;
	req.open("post","actions_ajax.php",true) ;
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded') ;
	req.send("action=saveInSession&route="+locations+"&w="+w) ;
}

/**
 * Sauvegarde l'itinéraire dans le carnet de voyage
 */
GIS.prototype.saveInDatabase = function() {
	var text = document.createElement("span") ;
	if (!this.auth) {
		text.innerHTML = I18N.mustConnect[this.lg] ;
		alert(text.innerHTML) ;
	} else {
		text.innerHTML = I18N.nameRoute[this.lg] ;
		var name = prompt(text.innerHTML, this.name.innerHTML) ;
		if (name != null) {
			name = urlencode(name) ;
			var locations = '' ;
			for (var i = 0 ; i < this.route.locations.length ; ++i) {
				var location = this.route.locations[i] ;
				if (location.id.charAt(0) != "u") {
					locations += location.id+',' ;
				} else {
					var lonlat = location.lonlat.clone() ;
					lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")) ;
					locations += lonlat.lon+'|'+lonlat.lat+'|'+urlencode(location.title)+',' ;
				}
			}
			if (locations.length > 0) locations = locations.substring(0, locations.length - 1) ;
			var req = createAjaxHTTPREQUEST() ;
			req.onreadystatechange = function() {
				if (req.readyState == 4 && req.status == 200) {
					var result = parseResponseText(req.responseText).documentElement ;
					if(result.getElementsByTagName("name")[0].firstChild) gis.name.innerHTML = result.getElementsByTagName("name")[0].firstChild.nodeValue ;
					if(result.getElementsByTagName("id")[0].firstChild) gis.routeID = result.getElementsByTagName("id")[0].firstChild.nodeValue ;
					text.innerHTML = I18N.routeSaved[gis.lg] ;
					alert(text.innerHTML) ;
				}
			}
			var w = (this.walk)?1:0 ;
			req.open("post","actions_ajax.php",true) ;
			req.setRequestHeader('Content-Type','application/x-www-form-urlencoded') ;
			req.send("action=saveInDatabase&route="+locations+"&name="+name+"&route_id="+this.routeID+"&w="+w) ;
		}
	}
}

/**
 * Récupère l'itinéraire actuel dans la session
 */
GIS.prototype.restoreFromSession = function() {
	var req = createAjaxHTTPREQUEST() ;
	req.onreadystatechange = function() {
		if (req.readyState == 4 && req.status == 200) {
			var result = parseResponseText(req.responseText).documentElement ;
			var locations = result.getElementsByTagName("location") ;
			var size = result.getElementsByTagName("size")[0].firstChild.nodeValue ;
			var locsArray = new Array() ;
			var minlonlat = new OpenLayers.LonLat(result.getElementsByTagName("minlon")[0].firstChild.nodeValue, 
				result.getElementsByTagName("minlat")[0].firstChild.nodeValue) ;
			var maxlonlat = new OpenLayers.LonLat(result.getElementsByTagName("maxlon")[0].firstChild.nodeValue, 
				result.getElementsByTagName("maxlat")[0].firstChild.nodeValue) ;
			minlonlat = minlonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
			maxlonlat = maxlonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
			gis.openLayersMap.zoomToExtent(new OpenLayers.Bounds(minlonlat.lon, minlonlat.lat, maxlonlat.lon, maxlonlat.lat)) ;
			for (var i = 0 ; i < locations.length ; ++i) {
				var location = locations[i] ;
				var id = location.getElementsByTagName("id")[0].firstChild.nodeValue ;
				var genre = 1 ;
				if (id == "user") {
					id = "user"+(gis.idBase++) ;
					genre = 0 ;
				}
				var position = location.getElementsByTagName("position")[0].firstChild.nodeValue ;
				var lonlat = new OpenLayers.LonLat(location.getElementsByTagName("longitude")[0].firstChild.nodeValue,
								location.getElementsByTagName("latitude")[0].firstChild.nodeValue) ;
				lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")) ;
				if (gis.locationsHash[id]) locsArray[position] = gis.locationsHash[id] ;
				else locsArray[position] = new Location(id, lonlat, position,
								(location.getElementsByTagName("title")[0].firstChild)?location.getElementsByTagName("title")[0].firstChild.nodeValue:'',
							(location.getElementsByTagName("description")[0].firstChild)?location.getElementsByTagName("description")[0].firstChild.nodeValue:'', genre) ;
			}
			gis.route.clear() ;
			gis.route.addLocations(locsArray) ;
		}
	}
	req.open("post","actions_ajax.php",true) ;
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded') ;
	req.send("action=restoreFromSession") ;
}

/**
 * Demande la création de l'itinéraire au serveur
 */
GIS.prototype.generateRoute = function() {
	var locations = '' ;
	for (var i = 0 ; i < this.route.locations.length ; ++i) {
		var location = this.route.locations[i] ;
		if (location.id.charAt(0) != "u") {
			locations += location.id+',' ;
		} else {
			var lonlat = location.lonlat.clone() ;
			lonlat = lonlat.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")) ;
			locations += lonlat.lon+'|'+lonlat.lat+'|'+urlencode(location.title)+',' ;
		}
	}
	if (locations.length > 0) locations = locations.substring(0, locations.length - 1) ;
	var req = createAjaxHTTPREQUEST() ;
		req.onreadystatechange = function() {
		if (req.readyState == 4 && req.status == 200) {
			var file = req.responseText ;
			if (gis.routeLayer == null) {
				gis.routeLayer = new OpenLayers.Layer.WMS('Route Layer','http://vtn.actimage-ext.net/cgi-bin/mapserv?map='+file, {layers: ['route'], transparent: 'true', reproject: 'true'}, {projection: 'epsg:900913', isBaseLayer: false});
				gis.routeLayer.maxResolution = gis.googleLayer.maxResolution ;
				gis.routeLayer.minResolution = gis.googleLayer.minResolution ;
				gis.routeLayer.maxScale = gis.googleLayer.maxScale ;
				gis.routeLayer.minScale = gis.googleLayer.minScale ;
				gis.routeLayer.resolutions = gis.googleLayer.resolutions ;
				gis.routeLayer.scales = gis.googleLayer.scales ;
				gis.openLayersMap.addLayer(gis.routeLayer) ;
				gis.routeLayer.setZIndex(320) ;
			} else {
				gis.routeLayer.redraw(true) ;
			}
		}
	}
	req.open("post","actions_ajax.php",true) ;
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded') ;
	req.send("action=generateRouteDisplay&route="+locations) ;
}

/**
 * Efface les résultats de recherche
 */
GIS.prototype.clearSearchResult = function() {
	this.radiusLayer.removeFeatures(this.radiusLayer.features) ;
	this.vectorLayer.removeFeatures(gis.outFeatures) ;
	gis.outFeatures = new Array() ;
}



/// Constantes chemin utilisées pour les marqueurs
var alpha = new Array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y') ;
GIS.ICON_PATH = new Array() ;
for (var i = 0 ; i < 25 ; i++)
	GIS.ICON_PATH[i] = './ico/icon_green'+alpha[i]+'.png' ;
GIS.DEPART_PATH = './ico/flag_d.png' ;
GIS.ARRIVEE_PATH = './ico/flag_a.png' ;
GIS.GENRE_PATH = new Array() ;
GIS.GENRE_PATH[2000001] = './ico/lodging.png' ;
GIS.GENRE_PATH[2000002] = './ico/camera.png' ;
GIS.GENRE_PATH[2000003] = './ico/restaurant.png' ;
GIS.GENRE_PATH[2000004] = './ico/info.png' ;
GIS.GENRE_PATH[2000005] = './ico/arts.png' ;
GIS.GENRE_PATH[0] = './ico/red.png' ;

/**
 * Classe Lieu
 * locationID : identifiant du lieu
 * lon : longitude
 * lat : latitude
 * position : position dans l'itinéraire
 * popupTitle : titre dans la popup
 * popupDescription : description dans la popup
 * genre : genre du lieu
 */
function Location(locationID, lonlat, position, popupTitle, popupDescription, genre) {

	/// Position sur l'itinéraire
	this.routePosition = position ;
	/// Longitude et latitude
	this.lonlat = lonlat ;
	/// Fonctionnalité associée (marqueur + popup)
	this.feature = null ;
	/// Titre dans la popup
	this.title = popupTitle ;
	/// Description dans la popup
	this.description = popupDescription ;
	/// Identifiant
	this.id = locationID ;
	/// Genre
	this.genre = genre ;

	gis.locationsHash[this.id] = this ;

}

/**
 * Supprime le marqueur associé de la carte
 */
Location.prototype.removeMarker = function() {
	if (this.feature != null) {
		gis.vectorLayer.removeFeatures(new Array(this.feature)) ;
	}
}

/**
 * Création et mise à jour du marqueur et de la popup de ce lieu
 */
Location.prototype.createUpdateFeature = function() {
	this.removeMarker() ;
	if (this.routePosition < 0) {
		var popupContent = '<h3>'+this.title+'</h3><p style="height: auto; overflow: auto">'+this.description+'</p>' ;
		popupContent += ((this.id.charAt(0) == 'u')?'':'<input type="button" value="'+I18N.moreLoc[gis.lg]+'" onclick="getLocationInformations('+this.id+', \'false\'); gis.openClosePopup(null)" /><br />') ;
		popupContent += ((gis.allowMod)?'<input type="button" value="'+I18N.addLoc[gis.lg]+'" onclick="gis.route.addLocation(gis.locationsHash[\''+this.id+'\']) ; gis.openClosePopup(null)" />':'<input type="button" value="'+I18N.addLoc[gis.lg]+'" onclick="addLocation('+this.id+') ; gis.openClosePopup(null)" />') ;
		this.feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(this.lonlat.lon, this.lonlat.lat), 
													this, {externalGraphic: GIS.GENRE_PATH[this.genre], graphicWidth: 35, graphicHeigth: 74, graphicYOffset: -37, graphicOpacity: 1}) ;
		gis.vectorLayer.addFeatures(new Array(this.feature)) ;
		gis.outFeatures.push(this.feature) ;

		this.feature.lonlat = this.lonlat;
		this.feature.data = {lonlat: this.lonlat, popupContentHTML: popupContent};

		var popup = this.feature.createPopup(true) ;
		popup.addCloseBox( function (e) {
			gis.openClosePopup(popup) ;
			OpenLayers.Event.stop(e);
		} ) ;
		popup.hide() ;
		gis.openLayersMap.addPopup(popup, false) ;

	} else {
		if (this.routePosition == 0) {
			var path = GIS.DEPART_PATH ;
		} else if (this.routePosition == (gis.route.locations.length - 1)) {
			var path = GIS.ARRIVEE_PATH ;
		} else {
			var path = GIS.ICON_PATH[this.routePosition%25] ;
		}
		var popupContent = '<h3>'+this.title+'</h3><p style="height: auto; overflow: auto">'+this.description+'</p>' ;
		popupContent += ((this.id.charAt(0) == 'u')?'':'<input type="button" value="'+I18N.moreLoc[gis.lg]+'" onclick="getLocationInformations('+this.id+', \'false\'); gis.openClosePopup(null)" /><br />') ;
		popupContent += ((gis.allowMod)?'<input type="button" value="'+I18N.delLoc[gis.lg]+'" onclick="gis.route.removeLocation('+this.routePosition+') ; gis.openClosePopup(null)" />':'<input type="button" value="'+I18N.addLoc[gis.lg]+'" onclick="addLocation('+this.id+') ; gis.openClosePopup(null)" />') ;
		this.feature = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(this.lonlat.lon, this.lonlat.lat), 
													this, {externalGraphic: path, graphicWidth: 35, graphicHeigth: 74, graphicYOffset: -37, graphicOpacity: 1}) ;
		gis.vectorLayer.addFeatures(new Array(this.feature)) ;

		gis.onFeatures.push(this.feature) ;

		this.feature.lonlat = this.lonlat;
		this.feature.data = {lonlat: this.lonlat, popupContentHTML: popupContent};

		var popup = this.feature.createPopup(true) ;
		popup.addCloseBox( function (e) {
			gis.openClosePopup(popup) ;
			OpenLayers.Event.stop(e);
		} ) ;
		popup.hide() ;
		gis.openLayersMap.addPopup(popup, false) ;

	}
	this.feature.location = this ;
}

/**
 * Classe Itinéraire
 * locsID : l'id de l'élément destiné à accueillir la liste des étapes
 * directionsID : l'id de l'élément destiné à accueillir la feuille de route
 */
function Route(locsID, directionsID) {

	/// Tableau des étapes de l'itinéraire
	this.locations = new Array() ;
	/// ID de l'élément destiné à accueillir la liste des étapes
	this.locsID = locsID ;
	/// ID de l'élément destiné à accueillir la feuille de route
	this.directionsID = directionsID ;
	/// Itinéraire en boucle ?
	this.isLoop = false ;
	/// Le calculateur d'itinéraire GoogleMaps (pour la feuille de route)
	this.googleDirection = new GDirections(null, document.getElementById(this.directionsID)) ;
	GEvent.addListener(this.googleDirection, 'addoverlay', function() {gis.route.drawMarkers();}) ;
}

/**
 * Ajout d'une étape
 * location : lieu à ajouter
 */
Route.prototype.addLocation = function(location) {
	if (this.locations.length < 25 || !gis.useGoogle) {
		var newPosition = this.locations.length ;
		this.locations.push(location) ;
		location.routePosition = newPosition ;
		this.redrawRoute() ;
	} else if (gis.useGoogle) {
		var text = document.createElement("span") ;
		text.innerHTML = I18N.locLimit[gis.lg] ;
		alert(text.innerHTML) ;
	}
}

/**
 * Ajout de plusieurs étapes
 * locations : lieux à ajouter
 */
Route.prototype.addLocations = function(locations) {
	var newPosition = this.locations.length ;
	for (var i = 0 ; i < locations.length ; ++i) {
		if (gis.useGoogle && this.locations.length >= 25) break ;
		this.locations.push(locations[i]) ;
		locations[i].routePosition = newPosition + i ;
	}
	this.redrawRoute() ;
}

/**
 * Suppression d'une étape
 * location : étape à supprimer
 */
Route.prototype.removeLocation = function(position) {
	this.locations[position].removeMarker() ;
	this.locations.splice(position,1) ;
	for(var i = position ; i < this.locations.length ; ++i)
		this.locations[i].routePosition -= 1 ;
	this.redrawRoute() ;
}

/**
 * Suppression de toutes les étapes
 */
Route.prototype.clear = function() {
	this.locations = new Array() ;
	gis.vectorLayer.removeFeatures(gis.onFeatures) ;
	gis.onFeatures = new Array() ;
}

/**
 * Déplace l'étape à la position donnée d'une place vers le départ
 * position : position de l'étape à déplacer
 */
Route.prototype.upLocationAtPosition = function(position) {
	var temp = this.locations[position] ;
	this.locations[position] = this.locations[position - 1] ;
	this.locations[position - 1] = temp ;
	this.locations[position].routePosition = position ;
	this.locations[position - 1].routePosition = position - 1 ;
	this.redrawRoute() ;
}

/**
 * Déplace l'étape à la position donnée d'une place vers l'arrivée
 * position : position de l'étape à déplacer
 */
Route.prototype.downLocationAtPosition = function(position) {
	var temp = this.locations[position] ;
	this.locations[position] = this.locations[position+1] ;
	this.locations[position + 1] = temp ;
	this.locations[position].routePosition = position ;
	this.locations[position + 1].routePosition = position + 1 ;
	this.redrawRoute() ;
}

/**
 * Recalcule et redessine l'itinéraire
 */
Route.prototype.redrawRoute = function() {
	if (gis.useGoogle) {
		gis.googleDirection.clear() ;
		gis.googleSatDirection.clear() ;
		gis.googlePhyDirection.clear() ;
		this.googleDirection.clear() ;
		if (this.locations.length > 1) {
			var addresses = new Array() ;
			for(var i = 0 ; i < this.locations.length ; ++i) {
				var projLoc = this.locations[i].lonlat.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")) ;
				addresses.push(projLoc.lat+','+projLoc.lon) ;
			}
			if (this.isLoop) {
				var projLoc = this.locations[0].lonlat.clone().transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326")) ;
				addresses.push(projLoc.lat+','+projLoc.lon) ;
			}

			gis.googleDirection.loadFromWaypoints(addresses, {preserveViewport: true, travelMode: (gis.walk)?G_TRAVEL_MODE_WALKING:G_TRAVEL_MODE_DRIVING}) ;
			gis.googleSatDirection.loadFromWaypoints(addresses, {preserveViewport: true, travelMode: (gis.walk)?G_TRAVEL_MODE_WALKING:G_TRAVEL_MODE_DRIVING}) ;
			gis.googlePhyDirection.loadFromWaypoints(addresses, {preserveViewport: true, travelMode: (gis.walk)?G_TRAVEL_MODE_WALKING:G_TRAVEL_MODE_DRIVING}) ;
			if (gis.waitForPrint) {
				GEvent.addListener(this.googleDirection, 'addoverlay', setTimeout("printDirections()", 1000)) ;
				gis.waitForPrint = false ;
			}
			if (gis.allowMod) this.googleDirection.loadFromWaypoints(addresses, {preserveViewport: true, locale: gis.lg.toLowerCase(), travelMode: (gis.walk)?G_TRAVEL_MODE_WALKING:G_TRAVEL_MODE_DRIVING}) ;
		}
	}
	this.drawMarkers() ;
	this.updateLocationsList() ;
}

/**
 * Dessine les marqueurs des lieux
 */
Route.prototype.drawMarkers = function() {
	
	if (gis.allowMod && gis.routeID == -1) gis.saveInSession() ;
	for(var i = 0 ; i < this.locations.length ; ++i)
		this.locations[i].createUpdateFeature() ;
}

/**
 * Met à jour la liste des étapes affichée
 */
Route.prototype.updateLocationsList = function() {
	if (document.getElementById(this.locsID) != null) {
		var html = '<table>' ;
		for (var i = 0 ; i < this.locations.length ; ++i) {
			html += '<tr><td><strong>' ;
			if (i == 0) {
				html += '<img src="./ico/flag_d.png" alt="'+I18N.start[gis.lg]+'" />' ;
			} else if (i == (this.locations.length - 1)) {
				html += '<img src="./ico/flag_a.png" alt="'+I18N.stop[gis.lg]+'" />' ;
			} else {
				html += '<img src="./ico/icon_green'+alpha[i%25]+'.png" alt="'+alpha[i]+'">' ;
			}
			html += this.locations[i].title ;
			html += '</strong></td>' ;
			if (gis.allowMod) {
				html += '<td><img src="images/up.png" '+((i == 0) ? 'style="visibility: hidden"' : '') ;
				html += ' onclick="gis.route.upLocationAtPosition('+i+')" title="'+I18N.up[gis.lg]+'" /></td>' ;
				html += '<td><img src="images/down.png" '+((i == this.locations.length - 1) ? 'style="visibility: hidden"' : '') ;
				html += ' onclick="gis.route.downLocationAtPosition('+i+')" title="'+I18N.down[gis.lg]+'" /></td>' ;
				html += '<td><img src="images/close.png" onclick="gis.route.removeLocation('+i+')" title="'+I18N.del[gis.lg]+'" /></td>' ;
			}
			html += '</tr>' ;
		}
		html += '</table>' ;
		document.getElementById(this.locsID).innerHTML = html ;
	}
}

/**
 * Permet de faire choisir l'étape de départ comme étape d'arrivée
 * id : l'ID du bouton pour mise à jour de l'intitulé
 */
Route.prototype.loopRoute = function(id) {
	this.isLoop = !this.isLoop ;
	document.getElementById(id).value = (this.isLoop) ? "Pas de boucle" : "Boucle" ;
	this.redrawRoute() ; 
}

