//$.get("/includes/xiti_ajax.jsp");
function ClusterMarker(point, bounds, title) {
  this.point_ = point;
  this.title_ = title;
  this.bounds_ = bounds;
};

ClusterMarker.prototype = new GOverlay();

ClusterMarker.prototype.initialize = function(map) {
  // Create the DIV representing our rectangle
  var div = document.createElement("div");

  $(div)
	  .addClass('clustermarker')
	  .attr('title', this.title_)
	  .css('cursor', 'pointer')
	  .tooltip({
		    extraClass: "gmaps_tooltip",
		    track: false,
		    delay: 0,
		    showURL: false,
		    showBody: " - "
	  });

  // Our rectangle is flat against the map, so we add our selves to the
  // MAP_PANE pane, which is at the same z-index as the map itself (i.e.,
  // below the marker shadows)
  map.getPane(G_MAP_MAP_PANE).appendChild(div);

  this.map_ = map;
  this.div_ = div;

  GEvent.bindDom(this.div_, 'mouseover', this, this.onMouseOver);
  GEvent.bindDom(this.div_, 'mouseout', this, this.onMouseOut);
};
ClusterMarker.prototype.onMouseOver = function() {
	this.map_.last_cluster = this;
};
ClusterMarker.prototype.onMouseOut = function() {
	this.map_.last_cluster = null;
};

ClusterMarker.prototype.getPoint = function() {
  return this.point_;
};

// Remove the main DIV from the map pane
ClusterMarker.prototype.remove = function() {
	this.div_.parentNode.removeChild(this.div_);

	// Petit hack pour eviter de se retrouver avec un cluster cliquable
	// alors qu'il n'est plus sur la map.
	if (this.map_.last_cluster == this) {
		this.map_.last_cluster = null;
		$('#tooltip').hide();
	}
};

// Copy our data to a new ClusterMarker
ClusterMarker.prototype.copy = function() {
  return new ClusterMarker(this.point_, this.bounds_, this.title_);
};

// Redraw the rectangle based on the current projection and zoom level
ClusterMarker.prototype.redraw = function(force) {
  // We only need to redraw if the coordinate system has changed
  if (!force) return;

  // Calculate the DIV coordinates of two opposite corners of our bounds to
  // get the size and position of our rectangle
  var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
  var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());

  // Now position our DIV based on the DIV coordinates of our bounds.
  // Borders de 1px, donc on retire 2px pour gauche+droite et haut+bas
  // pour prendre en compte ces borders.
  this.div_.style.width = Math.max(0, Math.abs(c2.x - c1.x) - 2) + "px";
  this.div_.style.height = Math.max(0, Math.abs(c2.y - c1.y) - 2) + "px";

  this.div_.style.left = Math.min(c2.x, c1.x) + "px";
  this.div_.style.top = Math.min(c2.y, c1.y) + "px";
};


// === A method for testing if a point is inside a polygon
// === Returns true if poly contains point
// === Algorithm shamelessly stolen from http://alienryderflex.com/polygon/ 
GPolygon.prototype.Contains = function(point) {
	
	// Optimisation
	if (!this.getBounds().containsLatLng(point)) return false;

	var j=0;
	var oddNodes = false;
	var x = point.lng();
	var y = point.lat();
	for (var i=0; i < this.getVertexCount(); i++) {
		j++;
		if (j == this.getVertexCount()) {j = 0;}
		if (((this.getVertex(i).lat() < y) && (this.getVertex(j).lat() >= y))
				|| ((this.getVertex(j).lat() < y) && (this.getVertex(i).lat() >= y))) {
			if ( this.getVertex(i).lng() + (y - this.getVertex(i).lat())
					/  (this.getVertex(j).lat()-this.getVertex(i).lat())
					*  (this.getVertex(j).lng() - this.getVertex(i).lng())<x ) {
				oddNodes = !oddNodes
			}
		}
	}
	return oddNodes;
};

// petit hack : on ajoute à la classe GPolygon une fonction getPoint qui
// renvoie à peu près le centre du polygone. Grace à ca on peut le passer dans
// le MarkerManager
GPolygon.prototype.getPoint = function() {
	return this.getBounds().getCenter();
};


function HtmlControl(_html, _options) {
	this._html=_html;
	this._opts = {
		isPrintable: false,
		isSelectable: false,
		isVisible: true
	};
	$.extend(this._opts,_options);
	this.show = function() {
		if (!this._opts.isVisible) {
			$(this._div).show();
			this._opts.isVisible = true;
		}
	};
	this.hide = function() {
		if (this._opts.isVisible) {
			$(this._div).hide();
			this._opts.isVisible = false;
		}
	};
};
HtmlControl.prototype=new GControl();
HtmlControl.prototype.initialize=function(_map) {
	this.selectable=function() {
		return this._opts.isSelectable;
	};
	this.printable=function() {
		return this._opts.isPrintable;
	};
	this._div=document.createElement('div');
	$(this._div).append(this._html);
	_map.getContainer().appendChild(this._div);
	return this._div;
};
HtmlControl.prototype.getDefaultPosition=function() {
	return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7,7));
};

function createZoomControl() {
	var img = $('<img class="fixpng" src="/imgs/maps/zoomcontrol.png"/>');
	var html = $('<div></div>').append(img);
	html.append('<div id="zoomfrance" title="'+libelles.zoomfrance+'"></div>');
	html.append('<div id="zoomagences" title="'+libelles.recentrercarte+'"></div>');
	html.append('<div id="resetmap" title="'+libelles.reinitcarte+'"></div>');
	$('div',html).css({
		position: 'absolute',
		cursor: 'pointer',
		left: '9px',
		width: '18px',
		height: '18px',
		backgroundColor: 'white',
		opacity: 0
	});
	$('#zoomfrance',html).css('top','2px');
	$('#zoomagences',html).css('top','20px');
	$('#resetmap',html).css('top','38px');
	return new HtmlControl(html);
}


GMap2.prototype.boundTo = function(bounds, delta) {
	if (typeof(delta) != "number") {
		delta = 0;
	}
	var zoom = this.getBoundsZoomLevel(bounds) + delta;
	if (zoom != this.getZoom()) {
		this.setCenter(bounds.getCenter(), zoom);
	} else {
		this.panTo(bounds.getCenter());
	}
};


var max_zoom_regions = -1;
var max_zoom_clustering = -1;

var map;
var mgr;
var geocoder;

var timeout;

// les polygones des regions
var regions = [];

var gicons = [];
// nom de l'icone agence defini dans gicons
var icon;


var recherche_markers = [];

var directions = null;

var loader_control = null;
var loader_status = {ajax: false, geocoder: false, directions: false};

var zoom_control = null;

// Libelles chargés depuis map.jsp
var libelles = {};

// Bounds correspondant à toutes les agences, chargé depuis map.jsp
var agencesBounds = new GLatLngBounds();

$(function() {
	
	$.ifixpng('/imgs/maps/pixel.gif');

	if (GBrowserIsCompatible()) {
		$(window).unload(GUnload);

		$('#panel').tabs({
			disabled: [1]
		});

		if ($('#options select').length < 1) {
			$('#options').hide();
		}
		$('#options form').hide();
		$('#options h2').click(function() {
			$('#options form').slideToggle();
			$(this).toggleClass('opened');
		});

		/*
		$(window).resize(function(){
			var height = $(window).height() - $("#map").offset().top - $("#footer").height() - 20;
			height = Math.max(height,0);
			$('#map,#panel,#mapsplitter,#td_contenu').height(height);
			$('.panelcontent').height(height - $('#panel > ul').height());
		}).trigger("resize");
		*/

		$('#mapsplitter').click(function(){
			var marge = parseInt($('#map').css('margin-left'));
			if ($('#panel').is(':visible')) {
				// si on fait une hide/show, le show ajoute un "display: block"
				// qui prend le dessus sur gmnoprint.
				$('#panel').addClass('gmnoscreen');
				$('#map').css('margin-left', marge + $(this).width() - $('#panel').width());
				$(this).addClass('collapsed');
			} else {
				$('#panel').removeClass('gmnoscreen');
				$('#map').css('margin-left', marge - $(this).width() + $('#panel').width());
				$(this).removeClass('collapsed');
			}
			map.checkResize();
		}).hover(
			function(){
				$(this).addClass('hover');
			},function(){
				$(this).removeClass('hover');
			}
		);


		// Sélection des éléments à masquer/afficher pour n'imprimer que l'itinéraire
		$('#masthead > * ').not('#logo_print').addClass('gmnoprint');
		$('#bloc_central > * ').not('#contenu').addClass('gmnoprint');
		$('#google_maps > *').not('#description_itineraire').addClass('gmnoprint');

		map = new GMap2(document.getElementById("map"));

		// la derniere region survolée à la souris
		map.last_region = null;

		// le dernier cluster survolé à la souris
		map.last_cluster = null;

		// bounds representant la France
		var franceBounds = new GLatLngBounds();
		franceBounds.extend(new GLatLng(42.3,-5));
		franceBounds.extend(new GLatLng(51.2,8.30));

		// bounds representant toutes les agences
		var bounds = agencesBounds;
		map.boundTo(bounds);

		// la derniere zone correspondant soit aux agences affichees sur la carte
		// soit au dernier résultat de recherche
		// On l'initialise avec ceux de toutes les agences
		map.last_bounds = new GLatLngBounds(bounds.getSouthWest(), bounds.getNorthEast());


		map.enableDragging();
		map.enableDoubleClickZoom();
		map.enableScrollWheelZoom();
		map.addControl(new GSmallMapControl());
		map.addControl(new GHierarchicalMapTypeControl());


		loader_control = new HtmlControl('<img class="fixpng" src="/imgs/maps/ajax-loader.gif"/>');
		map.addControl(loader_control, new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(75, 5)));


		zoom_control = createZoomControl();
		map.addControl(zoom_control, new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7, 110)));

		// avant de fixer tous les png qui en ont besoin, on les preloade sinon erreur
		$('img.fixpng').load(function() {
			$(this).ifixpng();
		});

		mgr = new MarkerManager(map);

		geocoder = new GClientGeocoder();
		directions = new Directions(
				map,
				$('#directions .resultat').get(0),
				function() {
					updateDescriptionItineraire();
					$("#panel").tabs("enable",1).tabs("select",1);
					map.closeInfoWindow();
				}
			);
		// marker utilisé comme base quand on veut faire un itinéraire entre ce dernier et une agence
		directions.fromMarker = null;


		gicons["agence"] = new GIcon();
		gicons["agence"].image = "/imgs/maps/logo_agence.png";
		gicons["agence"].shadow = "/imgs/maps/logo_agence_shadow.png";
		gicons["agence"].iconSize = new GSize(24, 24);
		gicons["agence"].shadowSize = new GSize(37, 24);
		gicons["agence"].iconAnchor = new GPoint(12, 12);
		gicons["agence"].infoWindowAnchor = new GPoint(12, 1);

		gicons["agence_goutte"] = new GIcon();
		gicons["agence_goutte"].image = "/imgs/maps/logo_agence_goutte.png";
		gicons["agence_goutte"].shadow = "/imgs/maps/logo_agence_goutte_shadow.png";
		gicons["agence_goutte"].iconSize = new GSize(20, 34);
		gicons["agence_goutte"].shadowSize = new GSize(37, 34);
		gicons["agence_goutte"].iconAnchor = new GPoint(9, 34);
		gicons["agence_goutte"].infoWindowAnchor = new GPoint(9, 2);
		gicons["agence_goutte"].infoShadowAnchor = new GPoint(18, 25);


		gicons["recherche"] = new GIcon(G_DEFAULT_ICON);

		GEvent.addListener(map, "zoomend", function(oldlevel, newlevel) {
			// Evite d'avoir le tooltip qui reste bêtement ouvert après avoir cliqué sur un cluster.
			$('#tooltip').hide();

			// Efface le dernier cluster en memoire
			map.last_cluster = null;
		});

		GEvent.addListener(map, "dragend", function() {
			var zoom = map.getZoom();
			if (zoom <= max_zoom_regions) {
				$('#map shape,svg').css('cursor','pointer');
			} else if (zoom <= max_zoom_clustering) {
				$('#map div.clustermarker').css('cursor','pointer');
			}
		});
		GEvent.addListener(map, "dragstart", function() {
			$('#tooltip').hide();
			var zoom = map.getZoom();
			if (zoom <= max_zoom_regions) {
				$('#map shape,svg').css('cursor','');
			} else if (zoom <= max_zoom_clustering) {
				$('#map div.clustermarker').css('cursor','');
			}
		});

		GEvent.addListener(map, "click", function(overlay,point) {
			// click sur une region
			if (point && map.getZoom() <= max_zoom_regions) {
				// TODO : à partir de la 2.88, les GPolygon sont cliquables et ca change tout...
				if (timeout) clearTimeout(timeout);
				var region = findRegion(point);
				if (region != null) {
					zoomRegion(region);
				}
			// click sur un cluster
			} else if (point && map.getZoom() > max_zoom_regions && map.getZoom() <= max_zoom_clustering && map.last_cluster) {
				map.boundTo(map.last_cluster.bounds_);
			// click sur une agence
			} else if (overlay && overlay.is_agence) {
				showAgence(overlay);
			}
		});

		GEvent.addListener(map, "mousemove", function(point) {
			if (map.getZoom() > max_zoom_regions) return;
			if (timeout) clearTimeout(timeout);
			var lat = point.lat();
			var lng = point.lng();
			timeout = setTimeout('hoverRegions('+lat+','+lng+')',20);
		});

		$('#map').ajaxStart(function() {
			check_loader({ajax: true});
		}).ajaxStop(function() {
			check_loader({ajax: false});
		});


		// On reinitialise le formulaire de recherche par adresse
		$('#rechercheadresse form').get(0).reset();
		$('#gmap_rechercher').get(0).disabled = false;

		// Les options : si ca change, on recharge ce qui doit être rechargé
		$('#options select').change(function() {
			if (null != directions.fromMarker) {
				// cas si on est en mode recherche
				rechercheAgenceDepuis(directions.fromMarker, true);
			} else {
				// cas si on est en mode normal : affichage de toutes les agences
				unloadMarkers();
				loadMarkers();
			}
		});

		$('#effaceritineraire').click(function() {
			directions.clear();
			$('#panel').tabs("select",0).tabs("disable",1);
		});

		/*
		$('#itineraireretour').click(function() {
			directions.retour();
		});
		*/

		$('#zoomfrance').click(function() {
			map.boundTo(franceBounds);
		});

		$('#zoomagences').click(function() {
			if (map.last_bounds) {
				map.boundTo(map.last_bounds);
			} else {
				map.boundTo(bounds);
			}
		});

		$('#resetmap').click(function() {
			var reload = false;
			$('#effaceritineraire').click();
			map.boundTo(bounds);
			if (! $('#rechercheadresse .resultat').is(':empty')) {
				effacerRechercheAgence();
				reload = true;
			}
			$('#rechercheadresse input[name=adresse]').focus();

			// test = true si les criteres sont deja par défaut (cad toutes les agences)
			var test = 0 == $.grep($('#options select').get(),function(s){return(0 !== s.selectedIndex);}).length;
			if (!test) {
				$('#options form').get(0).reset();
				reload = true;
			}
			if (reload) {
				unloadMarkers();
				loadMarkers();
			}
		});

		// on charge les markers regions/agences
		loadMarkers();

	}
});

function check_loader(options) {
	$.extend(loader_status,options);
	var test = false;
	$.each(loader_status, function() {
		if (this == true) {
			test = true;
		}
	});
	if (test) {
		loader_control.show();
	} else {
		loader_control.hide();
	}
}

function showAgence(agenceMarker) {
	var point = agenceMarker.getPoint();
	var loadingTimeout = setTimeout('map.openInfoWindowHtml(new GLatLng('+point.lat()+','+point.lng()+'),"Chargement...")',500);
	var xtmatch = /^.*-X\d+(\w+)$/.exec(location.pathname) || [];
	$.get(
		"/agences/jsp/map_info_agence.jsp?id_agence="+agenceMarker.id_agence+"&xtp=0"+(xtmatch[1] || ""),
		function (response) {
			var html = $(response);
			$("div.description",html).append(directions.getForm(agenceMarker, html, libelles));
			if (directions.fromMarker) {
				$('form input[name=address]', html).val(directions.markerToDirectionQuery(directions.fromMarker));
			}
			var finalisation = function(result) {
				agenceMarker.openInfoWindow(result[0]);
				map.last_infos_agence = result.clone();
				map.last_id_agence = agenceMarker.id_agence;
			};
			// On preload le picto agence afin d'obtenir ses dimensions, et en fonction
			// de ces dimensions on ajuste la taille.
			var imgsrc = $('img', html).attr('src');
			if (imgsrc) {
				var img = new Image();
				$(img).load(function() {
					$('img', html).parent().css('height',this.height);
					$('div.description', html).css('margin-left',(this.width + 10) + 'px');
					if (loadingTimeout) clearTimeout(loadingTimeout);
					finalisation(html);
				}).error(function() {
					// si erreur 404 :
					$('div.description', html).css('margin-left','10px');
					if (loadingTimeout) clearTimeout(loadingTimeout);
					finalisation(html);
				});
				img.src = imgsrc;
			} else {
				if (loadingTimeout) clearTimeout(loadingTimeout);
				finalisation(html);
			}
		}
	);

};

function hoverRegions(lat, lng) {
	var region = findRegion(new GLatLng(lat, lng));
	if (region == map.last_region) {
		return;
	}
	map.last_region = region;
	if (region == null) {
		$('#map shape,svg').attr('title','').css('cursor','');
	} else {
		// SVG dans firefox, ou shape si c'est du VML dans IE
		// On les fait tous bêtement parce que pas d'ID possible sur ces éléments
		$('#map shape,svg').attr('title',region.label_).css('cursor','pointer');
	}
};

// Si le point passé en parametre est dans une region, renvoie le GPolygon
// correspondant à cette region, null sinon.
function findRegion(point) {
	for (var i = 0; i < regions.length; i++) {
		if (regions[i].Contains(point)) {
			return regions[i];
			break;
		}
	}
	return null;
};

// region : GPolygon correspondant à la région
function zoomRegion(region) {
	map.closeInfoWindow();
	map.boundTo(region.getBounds(), 1);
};

function blockOptions() {
	$('#options select').each(function(){
		this.disabled = true;
	});
	$('#nbagences').hide();
	$('#agencesloading').show();
};
function unblockOptions() {
	$('#options select').each(function(){
		this.disabled = false;
	});
	$('#agencesloading').hide();
	$('#nbagences').show();
};

function loadMarkers() {
	// On bloque les options pour eviter d'en charger plusieurs de suite
	blockOptions();
	loadAgences();
};

function unloadMarkers() {
	regions = [];
	mgr.clearMarkers();
	map.closeInfoWindow();
	$('#nbagences').empty();
	max_zoom_regions = -1;
	max_zoom_clustering = -1;
};

function loadRegions() {
	// cas où l'affichage des régions est désactivé
	if (max_zoom_regions < 0) {
		mgr.refresh();
		// On reactive le "tableau de contrôle"
		unblockOptions();
		return;
	}
	// on charge les regions
	regions = [];
	$.get('/agences/jsp/regions.xml', function(xml) {
			$('poly',xml).each(function() {
				var label = $(this).attr("name");
				var color = $(this).attr("color");

				var pts = [];
				$("point", this).each(function() {
					pts.push(new GLatLng(
							parseFloat($(this).attr("lat")),
							parseFloat($(this).attr("lng"))
							)
						);
				});

				var poly = new GPolygon(pts,"#000000",1,1,color,0.5,{clickable: false});
				poly.label_ = label;
				regions.push(poly);
				
			});
			mgr.addMarkers(regions, 0, max_zoom_regions);
			mgr.refresh();
			// On reactive le "tableau de contrôle"
			unblockOptions();
			});
};

function loadAgences() {

	var specialite = $('#options select[name=specialite]').val();
	if (specialite == null) {
		specialite = "";
	}
	var marque = $('#options select[name=marque]').val();
	if (marque == null) {
		marque = "";
	}
	var service = $('#options select[name=service]').val();
	if (service == null) {
		service = "";
	}

	$.post("/servlet/Geo.srvl",
		{
			action: "agences",
			specialite: specialite,
			marque: marque,
			service: service

		}, function(xml) {

			// root element
			var markers = $('markers',xml);

			// On affiche le nb d'agences trouvées
			var nb_agences = 0;
			if (nb_agences = markers.attr('nb')) {
				var node = $('#nbagences');
				if (nb_agences == 0) {
					node.html(libelles.zeroagencestrouvees);
				} else if (nb_agences == 1) {
					node.html(libelles.uneagencestrouvees);
				} else {
					node.html("<strong>"+nb_agences+"</strong> "+libelles.xagencestrouvees);
				}
			}
			
			max_zoom_regions = parseInt(markers.attr('mzr'));
			max_zoom_clustering = parseInt(markers.attr('mzc'));
			icon = markers.attr('icon');

			// On recupere les bounds pour toutes les agences
			var min_lat = parseFloat(markers.attr("minlat"));
			var max_lat = parseFloat(markers.attr("maxlat"));
			var min_lng = parseFloat(markers.attr("minlng"));
			var max_lng = parseFloat(markers.attr("maxlng"));

			// Créaction des icones des différentes enseignes
			var enseignes = markers.attr('enseignes').split(/,/);
			$.each(enseignes, function(index, value) {
				if (!gicons[value]) {
					gicons[value] = new GIcon(gicons["agence"]);
					gicons[value].image = "/imgs/maps/logo_agence_"+value+".png";
				}
			});

			if (isNaN(min_lat) || isNaN(min_lng) || isNaN(max_lat) || isNaN(max_lng)) {
				map.last_bounds = null;
			} else {
				map.last_bounds = new GLatLngBounds();
				map.last_bounds.extend(new GLatLng(min_lat,min_lng));
				map.last_bounds.extend(new GLatLng(max_lat,max_lng));
			}

			var zoom = max_zoom_regions + 1; // premier niveau de zoom pour affichage des agences

			var tab_agences = [];
			var tab_clusters = [];

			var item; 

			// Cas où on utilise pas de clustering
			if (max_zoom_clustering < 0) {
				$('agc', xml).each(function (i, item) {
					var point = new GLatLng(parseFloat(item.getAttribute("lat")),
						parseFloat(item.getAttribute("lng")));
					var id =  item.getAttribute("id");
					var marker = createAgenceMarker(point, id, item.getAttribute("nom"), item.getAttribute("ens"));
					tab_agences.push(marker);
					});
				mgr.addMarkers(tab_agences, zoom);
				mgr.refresh();
				// On reactive le "tableau de contrôle"
				// maintenant car on ne charge pas les régions
				unblockOptions();
			} else {
				for (var level = zoom; level <= max_zoom_clustering + 1; level++) {
					tab_agences[level] = [];
					tab_clusters[level] = [];
				}

				$('agc', xml).each(function (i, item) {
					var point = new GLatLng(parseFloat(item.getAttribute("lat")),
						parseFloat(item.getAttribute("lng")));
					var id =  item.getAttribute("id");
					var level =  item.getAttribute("level");
					var marker = createAgenceMarker(point, id, item.getAttribute("nom"), item.getAttribute("ens"));
					tab_agences[level].push(marker);
				});

				$('clust', xml).each(function (i, item) {
					var sw_lat = parseFloat(item.getAttribute("sw_lat"));
					var sw_lng = parseFloat(item.getAttribute("sw_lng"));
					var ne_lat = parseFloat(item.getAttribute("ne_lat"));
					var ne_lng = parseFloat(item.getAttribute("ne_lng"));

					var bounds = new GLatLngBounds();
					bounds.extend(new GLatLng(sw_lat,sw_lng));
					bounds.extend(new GLatLng(ne_lat,ne_lng));

					var point = new GLatLng(parseFloat(item.getAttribute("lat")),
						parseFloat(item.getAttribute("lng")));
					var level =  item.getAttribute("level");
					var marker = createClusterMarker(point, $('agc', item), bounds);
					tab_clusters[level].push(marker);
				});

				for (var level = zoom; level <= max_zoom_clustering + 1; level++) {
					mgr.addMarkers(tab_agences[level], level);
					mgr.addMarkers(tab_clusters[level], level, level);
				}
				loadRegions();
			}
	});


};

function createAgenceMarker(point, id, nom, ens) {
	var marker = new GMarker(point, {title: nom, icon: (ens?gicons[ens]:gicons[icon])});
	$.extend(marker,{
		is_agence: true,
		id_agence: id
	});
	return marker;
};

function createClusterMarker(point, agcs, bounds) {
	var nb_max = agcs.length;
	var title = nb_max+' '+libelles.agencesdanszone+' - <p>';
	if (nb_max > 10) {
		nb_max = 10;
	}
	for (var i = 0; i < nb_max; i++) {
		title += agcs[i].getAttribute('nom').replace(/ /ig,'&nbsp;')+'<br/>';
	}
	if (nb_max != agcs.length) {
		var reste = agcs.length - nb_max;
		title += '... et '+reste+' ';
		if (reste == 1) {
			title += libelles.autreagence+'.';
		} else {
			title += libelles.autresagences+'.';
		}
	}
	title += "</p>";
	return new ClusterMarker(point, bounds, title, 1, '#000000','rgb(225,59,0)');
};

function simplifyPlacemark(p) {
	var result = {};
	$.each(p, function (k,v){
		if(typeof(v) == "object") {
			$.extend(result, simplifyPlacemark(v));
		} else if(typeof(v) == "string") {
			result[k] = v;
		}
	});
	return result;
};

function placemark2address(placemark) {
	var p = simplifyPlacemark(placemark);
	var adresse = p.ThoroughfareName;
	var ville = p.LocalityName;
	var lieux = p.DependentLocalityName;
	var cp = p.PostalCodeNumber;
	var dpt = p.SubAdministrativeAreaName;
	var rgn = p.AdministrativeAreaName;
	var tmp = [];

	if (adresse) {
		tmp.push(adresse);
	}
	if (lieux) {
		tmp.push(lieux);
	}
	if (ville || cp) {
		tmp.push($.trim((cp?cp:'') + ' ' + (ville?ville:'')));
	} 
	if (dpt || rgn) {
		if(dpt) {
			tmp.push(dpt);
		} else {
			tmp.push(rgn);
		}
	}
	return tmp.join(", ");
};


function rechercheAgence(p) {
	check_loader({geocoder: true});

	var q = "";
	if (typeof(p) == "string") {
		q = p;
	} else {
		q = p.adresse.value;
	}

	q = $.trim(q);

	// On précise si nécéssaire que la recherche se limite à la france :
	if (null == q.match(/[\W,-]+fr(?:ance)?$/i)) {
		q += ", France";
	}

	geocoder.getLocations(
		q,
		function (response) {
			switch(response.Status.code) {
				case G_GEO_SUCCESS:
					// En mode recherche, on n'affiche que le resultat de la recherche
					unloadMarkers();
					check_loader({geocoder: false});
					var placemarks = $(response.Placemark);
					var bounds = new GLatLngBounds();
					if (placemarks.length > 1) {
						effacerRechercheAgence();
						var resultat = $('#rechercheadresse .resultat').empty();
						resultat.html('<div class="fieldset"><p class="titre">Sélectionnez la bonne adresse</p><br /></div>');
						resultat = $('div.fieldset', resultat);
						placemarks.each(function() {
							var adresse = placemark2address(this);
							var a = $('<a href="javascript:void(0);">'+adresse+'</a>');
							var coords = this.Point.coordinates;
							var point = new GLatLng(coords[1],coords[0]);
							bounds.extend(point);
							var marker = new GMarker(point, {title: adresse, icon: gicons["recherche"]});
							map.addOverlay(marker);
							// On mémorise pour effacer plus tard...
							recherche_markers.push(marker);
							GEvent.addListener(marker, "click", function() {
								a.click();
								});
							a.click(function(){
								var data = $('<div><b>Adresse :</b><br/>'+adresse+'<br/><br/></div>');
								$('<a class="suite">Utiliser cette adresse</a>')
								.attr('href','javascript:void(0)')
								.appendTo(data)
								.click(function(){
									var rechmarker = new GMarker(marker.getPoint(), {
											title: 'Déplacez-moi',
											icon: gicons["recherche"],
											draggable: true
											}
										);
									rechmarker.nom = adresse;
									rechercheAgenceDepuis(rechmarker);
									});
								marker.openInfoWindow(data[0]);
								}).css('cursor', 'pointer');
							resultat.append(a).append('<br />');
						});
						$('<a class="gmap_effacer_recherche" href="javascript:void(0);">'+libelles.effacerrecherche+'</a>')
							.click(function() {
								effacerRechercheAgence();
								loadMarkers();
							}).appendTo(resultat);
						map.boundTo(bounds);

						// On memorise le secteur de la derniere recherche
						map.last_bounds = bounds;

					} else {
						var coords = placemarks.get(0).Point.coordinates;
						var adresse = placemarks.get(0).address;
						var marker = new GMarker(new GLatLng(coords[1],coords[0]), {title: 'Déplacez-moi', icon: gicons["recherche"], draggable: true});

						// pour pouvoir recuperer l'adresse plus tard
						marker.nom = adresse;

						rechercheAgenceDepuis(marker);
					}
					break;
				default:
					check_loader({geocoder: false});
					alert("Adresse inconnue.");
					break;
			}
		}
	);
};

function effacerRechercheAgence() {
	
	map.closeInfoWindow();

	// on unbind la liste des adresses/agences
	// avant de l'enlever du DOM
	$('#rechercheadresse .resultat a').unbind();
	$('#rechercheadresse .resultat').empty();

	$(recherche_markers).each(function() {
		map.removeOverlay(this);
		});
	recherche_markers = [];
	if (directions.fromMarker) {
		map.removeOverlay(directions.fromMarker);
	}
};

function rechercheAgenceDepuis(marker, update) {
	// On retire les events sur le marqueur, au cas où il y avait
	// plusieurs adresses possibles que que l'on devait cliquer dessus
	// pour selectionner l'adresse.
	// TODO: ce truc est toujours utile ?
	//GEvent.clearListeners(marker, "click");

	if (!update) {

		effacerRechercheAgence();

		directions.fromMarker = marker;
		GEvent.addListener(marker, "dragend", function() {
				// Si on déplace le marker, on ne peut plus garder le nom
				// on utilise alors "Point sur la carte", et on modifie la zone de recherche
				// avec le nouveau nom.
				marker.nom = "Point sur la carte";
				$('#gmap_rechercher').get(0).disabled = true;
				$('#rechercheadresse input[name=adresse]')
					.val(marker.nom)
					.unbind('focus')
					.one('focus', function(){
						$(this).val('');
						$('#gmap_rechercher').get(0).disabled = false;
					})
					.blur();
				rechercheAgenceDepuis(marker, true);
				});
		GEvent.addListener(marker, "remove", function() {
				marker = null;
				directions.fromMarker = null;
				recherche_markers = [];
				});
	}

	var specialite = $('#options select[name=specialite]').val();
	if (specialite == null) {
		specialite = "";
	}
	var marque = $('#options select[name=marque]').val();
	if (marque == null) {
		marque = "";
	}
	var service = $('#options select[name=service]').val();
	if (service == null) {
		service = "";
	}

	// TODO: pouvoir changer le parametre nb
	$.post("/servlet/Geo.srvl",
		{
			action: "recherche",
			nb: 10,
			lat: marker.getPoint().lat(),
			lng: marker.getPoint().lng(),
			specialite: specialite,
			marque: marque,
			service: service

		}, function(xml) {
			// on unbind la liste des adresses/agences
			// avant de l'enlever du DOM
			$('#rechercheadresse .resultat a').unbind();
			$('#rechercheadresse .resultat').empty();

			if (!update) {
			map.addOverlay(marker);
			} else {
			// On vire les anciens résultats si c'est un update
			$(recherche_markers).each(function() {
				map.removeOverlay(this);
				});
			// et on reinit la liste
			recherche_markers = [];
			}

			var bounds = new GLatLngBounds();
			bounds.extend(marker.getPoint());
			var agences = [];
			$('agc',xml).each(function(){
				var point = new GLatLng(parseFloat($(this).attr("lat")),
					parseFloat($(this).attr("lng")));
				var marker = createAgenceMarker(point, $(this).attr("id"), $(this).attr("nom"), $(this).attr("ens"));
				map.addOverlay(marker);
				recherche_markers.push(marker);
				bounds.extend(point);
				agences.push([marker,$(this).attr("nom"),$(this).attr("distance")]);
			});


			// On memorise le secteur de la derniere recherche
			map.last_bounds = bounds;

			var resultat = $('#rechercheadresse .resultat').empty();
			resultat.html('<div class="fieldset"><p class="titre">Résultat de votre recherche</p><br /></div>');
			resultat = $('div.fieldset', resultat);
			if (agences.length > 0) {
				if (!update) {
					map.boundTo(bounds);
				}
				$(agences).each(function(i){
					var agence = this[0];
					var nom = this[1];
					var distance = this[2];
					if (distance < 1000) {
					distance = distance + ' m';
					} else {
					distance = (Math.round(distance/100) / 10) + ' km';
					}
					var a = $('<a href="javascript:void(0);">'+distance+', '+nom+'</a>')
						.click(function(){
							showAgence(agence);
						});
					resultat.append(a).append('<br />');
				});
			} else {
				resultat.append('Aucun résultat.<br/>');
			}
			$('<a class="gmap_effacer_recherche" href="javascript:void(0);">'+libelles.effacerrecherche+'</a>')
				.click(function() {
					effacerRechercheAgence();
					loadMarkers();
				}).appendTo(resultat);


			$.get("/includes/xiti_ajax.jsp",{
				jsp:'xiti_ajax',
				xtrecherche:'agence:' + cleanString($('#rechercheadresse input[name=adresse]').val())
			});
		});
};

function updateDescriptionItineraire() {
	var marker = (typeof(directions.from) == "object")?directions.from:directions.to;
	if (marker && marker.is_agence) {
		if (marker.id_agence == map.last_id_agence) {
			$('#description_itineraire .description').html($('div.description',map.last_infos_agence).html());
			$('#description_itineraire .itineraire').html($('#directions .resultat').html());
		}
	}
};

