/*	MarkerManagerLite

	Stuff to do:
	an unload method to free all refs ?
	function closure on clusterMarker arguments - to check
	make clusterMarker event and icon customisable
	addMarkers to add markers instead of replacing any existing markers: 	this._markers.concat(this._markers, _markers);
	check for memory leaks - remove event handles
	finally optimise for speed
*/

MarkerManager=function(map, options) {
	this._map=map;
	this._markers=[];
	this._clusterMarkers=[];
	this._events=[];
	this._bounds=[];
	this._infoWindowOpenedMarker = null;
	this._infoWindowOpenRefToGMarker = null;
	this._categoriesIcons = {};
	this._categories = [];
	if (typeof(options) != 'undefined')
	{
		this._options = {};
		for (var myOption in options)
		{
			switch (myOption)
			{
				case 'categoriesHandlers':
					this.setCategoriesHandlers(options[myOption]);
				break;
				case 'clusterIcon':
					this._clusterIcon = options[myOption];
				break;
				case 'defaultIcon':
					this._defaultIcon = options[myOption];
				break;
				default:
					this._options[myOption] = options[myOption];
				break;
			}
		}
	}
	if (typeof(this._clusterIcon) == 'undefined')
	{
		alert('Vous devez fournir une GIcon pour le regroupement de points dans les options du constructeur de MarkerManager');
	}
};

MarkerManager.prototype.addMarkers=function(_markers) {
	var firstCenteredBound = new GLatLngBounds();
	if (this._markers.size() > 0)
	{
		for (var i=0; i<this._markers.size(); i++) {
			firstCenteredBound.extend(this._markers[i].getLatLng());
		}
	}
	for (var i=0; i<_markers.size(); i++) {
		_markers[i]._isVisible=false;
		_markers[i]._categoryShow=true;
		_markers[i]._clusterMarker = false;
		if (typeof(_markers[i].category) != 'undefined' && this._categories.indexOf(_markers[i].category) == -1)
		{
			this._categories.push(_markers[i].category);
		}
		firstCenteredBound.extend(_markers[i].getLatLng());
	}
	this._markers = this._markers.concat(_markers);
	this._bounds=[]; // Remise à vide des cases de markers
	this._map.setCenter(firstCenteredBound.getCenter(), this._map.getBoundsZoomLevel(firstCenteredBound));
	
};

MarkerManager.prototype.removeMarkersFromId = function(t_markers_id)
{
	var indiceFounded;
	for (var i = 0 ; i < t_markers_id.length ; i++)
	{
		var indiceFounded = null;
		for (var j = 0 ; j < this._markers.length && indiceFounded == null; j++)
		{
			if (this._markers[j].id == t_markers_id[i])
			{
				this._map.removeOverlay(this._markers[j]);
				indiceFounded = j;
			}
		}
		if (indiceFounded != null)
			this._markers.splice(indiceFounded, 1);
	}
	this._bounds=[]; // Remise à vide des cases de markers
};

MarkerManager.prototype.findIndice = function(indice) {
	GLog.write('in find o_marker.id:'+this._markers[indice].id+', indice:'+indice+', t_markers_id[i]:'+t_markers_id[i]);
};

MarkerManager.prototype.clearMarkers=function() {
	this._markers=[];
	this._clusterMarkers=[];
	this._events=[];
	this._bounds=[];
	this._map.clearOverlays();
};

MarkerManager.prototype._setHandlers=function() {
	this.moveEndHandler = GEvent.bind(this._map, "moveend", this, this.refreshByMove);
	this.zoomEndHandler = GEvent.bind(this._map, "zoomend", this, this.refresh);
	this.infoWindowOpenHandler = GEvent.bind(this._map, "infowindowopen", this, this.onInfoWindowOpen);
	this.infoWindowCloseHandler = GEvent.bind(this._map, "infowindowclose", this, this.onInfoWindowClose);
};

MarkerManager.prototype._removeHandlers=function() {
	if (typeof(this.moveEndHandler) != 'undefined') GEvent.removeListener(this.moveEndHandler);
	if (typeof(this.zoomEndHandler) != 'undefined') GEvent.removeListener(this.zoomEndHandler);
	if (typeof(this.infoWindowOpenHandler) != 'undefined') GEvent.removeListener(this.infoWindowOpenHandler);
	if (typeof(this.infoWindowCloseHandler) != 'undefined') GEvent.removeListener(this.infoWindowCloseHandler);
};

MarkerManager.prototype.refreshByMove = function()
{
	if (!this._map.getBounds().equals(this._mapBound))
	{
		this.refresh();
	}
};


MarkerManager.prototype.onInfoWindowOpen = function()
{
	
	infoWindowLatLng = this._map.getInfoWindow().getPoint();
	clusterMarkerFounded = false;
	if (this._clusterMarkers.length > 0)
	{
		for (var i = 0 ; i < this._clusterMarkers.length && clusterMarkerFounded == false; i++)
		{
			if (this._clusterMarkers[i].getLatLng().equals(infoWindowLatLng))
			{
				clusterMarkerFounded = this._clusterMarkers[i];
			}
		}
	}
	
	
	if (clusterMarkerFounded != false)
	{
		this.infoWindowOpenMaximizeClusterHandler = GEvent.bind(this._map.getInfoWindow(), "maximizeclick", this, this.onInfoWindowClusterMaximize);
		this.infoWindowOpenRestoreClusterHandler = GEvent.bind(this._map.getInfoWindow(), "restoreclick", this, this.onInfoWindowClusterRestore);
		this.infoWindowOpenRestoreEndClusterHandler = GEvent.bind(this._map.getInfoWindow(), "restoreend", this, this.onInfoWindowClusterRestoreEnd);
		this._map.getInfoWindow().disableMaximize();
		if (this._infoWindowOpenedMarker != null) 
		{
			this._map.removeOverlay(this._infoWindowOpenedMarker);
		}
		this._infoWindowOpenedMarker = clusterMarkerFounded;
	}
	else
	{
		this.infoWindowOpenRestoreHandler = GEvent.bind(this._map.getInfoWindow(), "restoreend", this, this.onInfoWindowRestore);
	}
};

MarkerManager.prototype.onInfoWindowClose = function()
{
	if (this._infoWindowOpenedMarker != null) 
	{
		if (typeof(this.infoWindowOpenMaximizeClusterHandler) != 'undefined') GEvent.removeListener(this.infoWindowOpenMaximizeClusterHandler);
		if (typeof(this.infoWindowOpenRestoreClusterHandler) != 'undefined') GEvent.removeListener(this.infoWindowOpenRestoreClusterHandler);
		if (typeof(this.infoWindowOpenRestoreEndClusterHandler) != 'undefined') GEvent.removeListener(this.infoWindowOpenRestoreEndClusterHandler);
		this._map.removeOverlay(this._infoWindowOpenedMarker);
		for (i=0; i<this._clusterMarkers.size(); i++) {
			if (this._clusterMarkers[i].getLatLng().equals(this._infoWindowOpenedMarker.getLatLng()))
			{
				this._map.addOverlay(this._clusterMarkers[i]);
			}
		}
		this._infoWindowOpenedMarker = null;
	}
	else if (typeof(this.infoWindowOpenRestoreHandler) != 'undefined') this.infoWindowOpenRestoreHandler =  GEvent.removeListener(this.infoWindowOpenRestoreHandler);
};

MarkerManager.prototype.onInfoWindowClusterMaximize = function()
{
	
};
MarkerManager.prototype.onInfoWindowClusterRestore = function()
{
	this._map.getInfoWindow().disableMaximize();
	this._map.panTo(this._infoWindowOpenedMarker.getLatLng());
};
MarkerManager.prototype.onInfoWindowClusterRestoreEnd = function()
{
	var _t_infoWindowContent = this._map.getInfoWindow().getContentContainers();
	/*for (var n in _t_infoWindowContent[0])
	{
		GLog.write(n+' '+_t_infoWindowContent[0][n]);
	}*/
};



MarkerManager.prototype.onInfoWindowRestore = function()
{
	this._map.panTo(this._map.getInfoWindow()[this._infoWindowOpenRefToGMarker].getLatLng());
};

MarkerManager.prototype.refresh=function(oldZoom, newZoom) {
	this._removeHandlers();
	this._mapBound = this._map.getBounds();
	if (this._infoWindowOpenedMarker != null && typeof(newZoom) != 'undefined')
	{
		this._map.closeInfoWindow();
		this._map.removeOverlay(this._infoWindowOpenedMarker);
		this._infoWindowOpenedMarker = null;
	}
	var i, j;
	for (i=0; i<this._clusterMarkers.size(); i++) {
		if (typeof(newZoom) != 'undefined' || this._infoWindowOpenedMarker == null || this._clusterMarkers[i].getLatLng().equals(this._infoWindowOpenedMarker.getLatLng()) == false)
		{
			this._map.removeOverlay(this._clusterMarkers[i]);
		}
	}
	this._clusterMarkers=[];
	this._containedMarkers();
	if (this._map.getZoom()<this._map.getCurrentMapType().getMaximumResolution() && this._markers.size()>0) {
		this._nonIntersectingMarkers();
	}
	for (i=0; i<this._markers.size(); i++) {
		if (this._markers[i]._makeVisible && !this._markers[i]._isVisible) {
			this._map.addOverlay(this._markers[i]);
			this._markers[i]._isVisible=true;
		}
		if (!this._markers[i]._makeVisible && this._markers[i]._isVisible) {
			this._map.removeOverlay(this._markers[i]);
			this._markers[i]._isVisible=false;
		}
		
		if (this._markers[i]._isVisible == true)
		{
			if (this._markers[i]._categoryShow == true)
			{
				this._markers[i].show();
			}
			else if (this._markers[i]._categoryShow == false)
			{
				this._markers[i].hide();
			}
		}
	}
	for (i=0; i<this._clusterMarkers.size(); i++) {
		if (typeof(newZoom) != 'undefined' || this._infoWindowOpenedMarker == null || this._clusterMarkers[i].getLatLng().equals(this._infoWindowOpenedMarker.getLatLng()) == false)
		{
			this._map.addOverlay(this._clusterMarkers[i]);
		}
	}
	this._setHandlers();
};

MarkerManager.prototype._containedMarkers=function() {
	var _bounds=this._map.getBounds();
	var sw=_bounds.getSouthWest();
	var _swPoint=this._map.getCurrentMapType().getProjection().fromLatLngToPixel(sw, this._map.getZoom());
	var _newSwPoint=new GPoint(_swPoint.x-256, _swPoint.y+256);
	sw=this._map.getCurrentMapType().getProjection().fromPixelToLatLng(_newSwPoint, this._map.getZoom(), true);
	var ne=_bounds.getNorthEast();
	var _nePoint=this._map.getCurrentMapType().getProjection().fromLatLngToPixel(ne, this._map.getZoom());
	var _newNePoint=new GPoint(_nePoint.x+256, _nePoint.y-256);
	ne=this._map.getCurrentMapType().getProjection().fromPixelToLatLng(_newNePoint, this._map.getZoom(), true);
	_bounds=new GLatLngBounds(sw, ne);
	//this.drawRectangle(_bounds,'#ff0000');
	for (var i=0; i<this._markers.size(); i++) {
		this._markers[i]._makeVisible=_bounds.contains(this._markers[i].getLatLng())?true:false;
	}
};

MarkerManager.prototype.drawRectangle = function (bound, color)
		{
			var sw = bound.getSouthWest();
			var ne = bound.getNorthEast();
			var myPoly = new GPolygon([
				new GLatLng(sw.lat(), sw.lng()),
				new GLatLng(ne.lat(), sw.lng()),
				new GLatLng(ne.lat(), ne.lng()),
				new GLatLng(sw.lat(), ne.lng()),
				new GLatLng(sw.lat(), sw.lng())
			  ], color, 1, 1, color, 0.2);
			this._map.addOverlay(myPoly);
		};

MarkerManager.prototype._nonIntersectingMarkers=function() {
	var _clusterGroup, i, j, z='_'+this._map.getZoom();
	if (typeof(this._bounds[z])=='undefined') {
		this._bounds[z]=this._markersBoundsArray();
	}
	for (i=0; i<this._markers.size(); i++)
	{
		if (this._markers[i]._makeVisible && this._markers[i]._categoryShow) {
			_clusterGroup=[];
			for (j=i+1; j<this._markers.size(); j++) {
				if (this._markers[j]._makeVisible && this._bounds[z][i].intersects(this._bounds[z][j]) && this._markers[j]._categoryShow) {
					_clusterGroup.push(j);
				}
			}
			if (_clusterGroup.size()!==0) {
				for (j=0; j<_clusterGroup.size(); j++) {
					this._markers[_clusterGroup[j]]._makeVisible=false;
				}
				_clusterGroup.push(i);
				this._markers[i]._makeVisible=false;
				this._clusterMarkers.push(this._centerAndZoomMarker(_clusterGroup));
			}
		}
	}
};

MarkerManager.prototype._markersBoundsArray=function() {
	var _bounds=[], _anchorPoint, _boundsSw, _boundsNe, _icon, _iconWidth, _iconHeight, _iconAnchorX, _iconAnchorY, i, j, k, z, intersectMargin;
	intersectMargin=0;	//	maximum number of pixels to overlap before icon clustered - add to constructor?
	for (i=0; i<this._markers.size(); i++) {
		_icon=this._markers[i].getIcon();
		j=_icon.iconSize;
		_iconWidth=j.width;
		_iconHeight=j.height;
		j=_icon.iconAnchor;
		_iconAnchorX=j.x;
		_iconAnchorY=j.y;
		j=this._markers[i].getLatLng();
		k=this._map.getCurrentMapType().getProjection();
		z=this._map.getZoom();
		_anchorPoint=k.fromLatLngToPixel(new GLatLng(j.lat(),j.lng()), z);
		_boundsSw=k.fromPixelToLatLng(new GPoint(_anchorPoint.x-_icon.iconAnchor.x+intersectMargin, _anchorPoint.y-_iconAnchorY+_iconHeight-intersectMargin), z);
		_boundsNe=k.fromPixelToLatLng(new GPoint(_anchorPoint.x-_icon.iconAnchor.x+_icon.iconSize.width-intersectMargin, _anchorPoint.y-_icon.iconAnchor.y+intersectMargin), z);
		_bounds[i]=new GLatLngBounds(_boundsSw, _boundsNe);
	}
	return _bounds;
};


MarkerManager.prototype._centerAndZoomMarker=function(_clusterGroup) {
	var _number=_clusterGroup.size();
	var _point=this._markers[_clusterGroup[_clusterGroup.size()-1]].getLatLng();
	var _t_markers = [];
	var _bounds=new GLatLngBounds();
	var _cpt_Categories = {};
	for (var i=0; i<_number; i++) {
		if (typeof(_cpt_Categories[this._markers[_clusterGroup[i]].category]) == 'undefined')  _cpt_Categories[this._markers[_clusterGroup[i]].category] = 0;
		_cpt_Categories[this._markers[_clusterGroup[i]].category]++;
		_bounds.extend(this._markers[_clusterGroup[i]].getLatLng());
		_t_markers.push(this._markers[_clusterGroup[i]]);
	}
	if (typeof(getClusterMarkerTitle) == 'function')
	{
		var _title = getClusterMarkerTitle(_t_markers);
	}
	else
	{
		var txt_categorie = '';
		for (var categ in _cpt_Categories)
		{
			txt_categorie += '['+categ+':'+_cpt_Categories[categ]+']';
		}
		var _title = 'Click to zoom in and see '+_number+' locations ('+txt_categorie+')'
	}
	
	if (typeof(LabeledMarker) == 'function')
	{
		var _marker=new LabeledMarker(_point, {icon:this._clusterIcon, title:_title, "clickable" : true, "labelText": _number, "labelOffset": new GSize(-16, -10)});
	}
	else
	{
		var _marker=new GMarker(_point, {icon:this._clusterIcon, title:_title});
	}
	_marker._clusterMarker = true;
	var linkSeRapprocher = new Element('a');
	linkSeRapprocher.onclick = GEvent.callbackArgs(this, this.getLinkToCenterAndZoom, _bounds, _marker);
	
	
	GEvent.addListener(_marker, 'click', function() {
		_marker.openInfoWindow(getInfoWindowForClusteredMarkers(_t_markers, linkSeRapprocher));
	});
	
	return _marker;
};

if (typeof(LabeledMarker) != 'function')
{
	GMarker.prototype.bindInfoWindow = GMarker.prototype.bindInfoWindow.wrap(
		function(proceed, parameters)
		{
			if(parameters.container && parameters.options)
			{
				proceed(parameters.container, parameters.options);
			}
			else
			{
				proceed(parameters.container);
			}
		}
	);
	GMarker.prototype.openInfoWindow = GMarker.prototype.openInfoWindow.wrap(
		function(proceed, parameters)
		{
			if(parameters.container && parameters.options)
			{
				proceed(parameters.container, parameters.options);
			}
			else
			{
				proceed(parameters.container);
			}
		}
	);
}
else
{
	LabeledMarker.prototype.bindInfoWindow = LabeledMarker.prototype.bindInfoWindow.wrap(
		function(proceed, parameters)
		{
			if(parameters.container && parameters.options)
			{
				proceed(parameters.container, parameters.options);
			}
			else
			{
				proceed(parameters.container);
			}
		}
	);
	LabeledMarker.prototype.openInfoWindow = LabeledMarker.prototype.openInfoWindow.wrap(
		function(proceed, parameters)
		{
			if(parameters.container && parameters.options)
			{
				proceed(parameters.container, parameters.options);
			}
			else
			{
				proceed(parameters.container);
			}
		}
	);
}

MarkerManager.prototype.getLinkToCenterAndZoom=function(_bounds, _marker) {
	if (typeof(this.infoWindowOpenMaximizeClusterHandler) != 'undefined') GEvent.removeListener(this.infoWindowOpenMaximizeClusterHandler);
	if (typeof(this.infoWindowOpenRestoreClusterHandler) != 'undefined') GEvent.removeListener(this.infoWindowOpenRestoreClusterHandler);
	if (typeof(this.infoWindowOpenRestoreHandler) != 'undefined') GEvent.removeListener(this.infoWindowOpenRestoreHandler);
	this._infoWindowOpenedMarker = null;
	this._map.removeOverlay(_marker);
	if (typeof(this._options.hideLoadingFunction) == "function")
		this._options.hideLoadingFunction();
	return this._map.setCenter(_bounds.getCenter(), this._map.getBoundsZoomLevel(_bounds));
};

/**
* Lance les init des handlers sur les checkbox de catégorie
* @param (Array) t_categorie [categoryName] => categoryCheckBoxName
*/
MarkerManager.prototype.setCategoriesHandlers = function(t_categorie)
{
	for (var categoryName in t_categorie)
	{
		GEvent.bindDom(document.getElementById(t_categorie[categoryName]), 'change', this, GEvent.callbackArgs(this, this.bindCategoryHandler, document.getElementById(t_categorie[categoryName]), categoryName, true));
		this.bindCategoryHandler(document.getElementById(t_categorie[categoryName]), categoryName);
	}
};

/**
* Change l'état de l'attribut this.categoryDisplayed.categoryName en fonction de l'état de la checkbox relative à la catégorie
* @param (DomObject) categoryDomObject : Objet DOM représentant l'état de visibilité de la catégorie (une checkbox en général)
* @param (String) categoryName : Nom de la catégorie
* @param (Boolean) updateCategoryVisibility : Met à jour 
*/
MarkerManager.prototype.bindCategoryHandler = function(categoryDomObject, categoryName, updateCategoryVisibility)
{
	if (typeof(this.categoryDisplayed) == 'undefined') this.categoryDisplayed = {};
	eval('this.categoryDisplayed['+categoryName+'] = '+categoryDomObject.checked);
	if (typeof(updateCategoryVisibility) != 'undefined' && updateCategoryVisibility == true)
	{
		this.togglingCategoryDisplay();
	}
};

/**
* Change les options pour n'afficher que la catégorie passée en paramètre
*@param(Mixed) category : Catégorie à afficher
*/
MarkerManager.prototype.affichageExclusifCategory = function(categoryName)
{
	// Si une infoWindow est affichée, je la ferme
	if (this._map.getInfoWindow().isHidden() == false)
	{
		this._map.closeInfoWindow();
		this._infoWindowOpenedMarker = null;
	}
	this.categoryDisplayed = {};
	eval('this.categoryDisplayed['+categoryName+'] = true');
	this.togglingCategoryDisplay(true);
	if (typeof(this._options.hideLoadingFunction) == "function")
		this._options.hideLoadingFunction();
};

/**
* Change les options pour afficher toutes les catégories
*/
MarkerManager.prototype.afficherToutesCategories = function()
{
	this.categoryDisplayed = {};
	for (var i = 0 ; i < this._categories.size() ; i++)
	{
		eval('this.categoryDisplayed['+this._categories[i]+'] = true');
	}
	this.togglingCategoryDisplay(true);
	if (typeof(this._options.hideLoadingFunction) == "function")
		this._options.hideLoadingFunction();
};

/**
* Change les options pour n'afficher que le GMarker dont l'indice du tableau _markers est passé en paramètre
*@param(Integer) i_marker : Indice du tableau de marker
*@param(Object) options : Options, openInfoWindow==true ouvre l'infowindow du marker
*/
MarkerManager.prototype.affichageExclusifMarker = function(i_marker, options)
{
	for (var i = 0 ; i < this._markers.size() ; i++)
	{
		if (i == i_marker)
		{
			this._markers[i]._categoryShow = true;
		}
		else
		{
			this._markers[i]._categoryShow = false;
		}
	}
	this.refresh();
	if (typeof(options) == 'object')
	{
		if (typeof(options.openInfoWindow) != 'undefined' && options.openInfoWindow == true && typeof(options.openInfoWindowOptions) == 'object' && typeof(options.openInfoWindowOptions.content) == 'string' && options.openInfoWindowOptions.content != '')
		{
			this._markers[i_marker].openInfoWindowHtml(options.openInfoWindowOptions.content, options.openInfoWindowOptions);
		}
	}
	if (typeof(this._options.hideLoadingFunction) == "function")
		this._options.hideLoadingFunction();
};


/**
* Affiche ou cache différentes catégories de markers
* @param(Boolean) autoAdjustMap : Si == true, ajuste le zoom et le centre de la carte pour contenir tous les points qui doivent s'afficher
*/
MarkerManager.prototype.togglingCategoryDisplay = function(autoAdjustMap)
{
	if (typeof(autoAdjustMap) != 'undefined' && autoAdjustMap == true)
	{
		var tmpBound = new GLatLngBounds();
	}
	for (var i = 0 ; i < this._markers.size() ; i++)
	{
		if (eval('this.categoryDisplayed['+this._markers[i].category+']'))
		{
			this._markers[i]._categoryShow = true;
			if (typeof(autoAdjustMap) != 'undefined' && autoAdjustMap == true)
			{
				tmpBound.extend(this._markers[i].getLatLng());
			}
		}
		else
		{
			this._markers[i]._categoryShow = false;
		}
	}
	if (this._infoWindowOpenedMarker != null)
	{
		this._map.removeOverlay(this._infoWindowOpenedMarker);
		this._infoWindowOpenedMarker = null;
	}
	if (typeof(autoAdjustMap) != 'undefined' && autoAdjustMap == true)
	{
		this._map.setCenter(tmpBound.getCenter(), this._map.getBoundsZoomLevel(tmpBound));
	}
	else
	{
		this.refresh();
	}
};

/**
* Recherche un point GPS à partir d'une adresse
* @param (Object) adressObj : Objet définissant une adresse (avec comme attributs 'adresse', 'code_postal', 'ville' et 'pays')
* @param (MarkerManager) myMarkerManager : Objet courant, nécessaire pour pouvoir y accéder dans la closure getLocations()
* @param (Integer) profondeur : Indique le niveau de profondeur pour la recherche : 0 = adresse+code_postal+ville+pays ; 1 = code_postal+ville+pays ; 2 = ville+pays ; 3 = pays
* @return (GLatLng) : point GPS trouvé
*/
MarkerManager.prototype.searchAdress = function(adressObj, myMarkerManager, profondeur)
{
	debug = true;
	
	this.adressSearching = true;
	if (debug == true) {GLog.write("Recherche de l'adresse : "+Object.print_r(adressObj)+", profondeur:"+profondeur);}
	
	
	// Construction de l'adresse à rechercher selon la profondeur
	var adresseComplete = '';
	if (typeof(profondeur) == 'undefined') profondeur = 0;
	switch (profondeur)
	{
		case 0:
			if (typeof(adressObj.adresse) != 'undefined') adresseComplete += adressObj.adresse;
			if (adresseComplete != '') adresseComplete += ', ';
			if (typeof(adressObj.code_postal) != 'undefined') adresseComplete += adressObj.code_postal;
			if (adresseComplete != '') adresseComplete += ', ';
			if (typeof(adressObj.ville) != 'undefined') adresseComplete += adressObj.ville;
			if (adresseComplete != '') adresseComplete += ', ';
			if (typeof(adressObj.pays) != 'undefined') adresseComplete += adressObj.pays;
		break;
		
		case 1:
			if (typeof(adressObj.code_postal) != 'undefined') adresseComplete += adressObj.code_postal;
			if (adresseComplete != '') adresseComplete += ', ';
			if (typeof(adressObj.ville) != 'undefined') adresseComplete += adressObj.ville;
			if (adresseComplete != '') adresseComplete += ', ';
			if (typeof(adressObj.pays) != 'undefined') adresseComplete += adressObj.pays;
		break;
		
		case 2:
			if (typeof(adressObj.ville) != 'undefined') adresseComplete += adressObj.ville;
			if (adresseComplete != '') adresseComplete += ', ';
			if (typeof(adressObj.pays) != 'undefined') adresseComplete += adressObj.pays;
		break;
		
		case 3:
			if (typeof(adressObj.pays) != 'undefined') adresseComplete += adressObj.pays;
		break;
	}
	
	if (adresseComplete == '')
	{
		if (debug == true) GLog.write('Adresse de recherche vide');
		return false;
	}
	
	
	
	var myGeocoder = new GClientGeocoder();
	myGeocoder.getLocations(adresseComplete, 
		function(point)
		{
			debug = true;
			var hebergementLat;
			var hebergementLong;
			if (!point)
			{
				if (debug) {GLog.write("Ville inconnue : "+point);}
				profondeur++;
				if (profondeur <= 3)
				{
					myMarkerManager.searchAdress(adressObj, myMarkerManager, profondeur);
				}
				else if (typeof(myMarkerManager._options.urlForCoordinatesUpdate) != "undefined")
				{
					var maRequete = new Ajax.Request(myMarkerManager.urlForCoordinatesUpdate+'&id_hebergement='+adressObj.id+'&hazard='+Math.random());
					myMarkerManager.pointFounded = false;
					myMarkerManager.adressSearching = false;
				}
				else
				{
					myMarkerManager.pointFounded = false;
					myMarkerManager.adressSearching = false;
				}
			}
			else {
				if (!point.Placemark)
				{
					if (debug) {GLog.write("Ville : "+point+", status : "+point.Status);}
					if (debug) {
						for (n in point.Status)
						{
							GLog.write(n+" : "+point.Status[n]);
						}
					}
					profondeur++;
					if (profondeur <= 3)
					{
						myMarkerManager.searchAdress(adressObj, myMarkerManager, profondeur);
					}
					else if (typeof(myMarkerManager._options.urlForCoordinatesUpdate) != "undefined")
					{
						var maRequete = new Ajax.Request(myMarkerManager._options.urlForCoordinatesUpdate+'&id_hebergement='+adressObj.id+'&hazard='+Math.random());
						myMarkerManager.pointFounded = false;
						myMarkerManager.adressSearching = false;
					}
					else
					{
						myMarkerManager.pointFounded = false;
						myMarkerManager.adressSearching = false;
					}
				}
				else if (point.Placemark.length == 1)
				{
					if (debug) {GLog.write('Précision : '+point.Placemark[0].AddressDetails.Accuracy);}
					villeDepartLibelle = myMarkerManager.construireAddressDetail(point.Placemark[0]);
					if (debug) {GLog.writeHtml('Ville trouvée : <b>'+villeDepartLibelle+'</b> <br />'+point.Placemark[0].Point.coordinates[1]+'X'+point.Placemark[0].Point.coordinates[0]);}
					hebergementLat = point.Placemark[0].Point.coordinates[1];
					hebergementLong = point.Placemark[0].Point.coordinates[0];
					
					if (typeof(myMarkerManager._options.urlForCoordinatesUpdate) != "undefined")
					{
						var maRequete = new Ajax.Request(myMarkerManager._options.urlForCoordinatesUpdate+'&id_hebergement='+adressObj.id+'&gps_lat='+hebergementLat+'&gps_lng='+hebergementLong+'&precision='+point.Placemark[0].AddressDetails.Accuracy+'&hazard='+Math.random());
					}
					myMarkerManager.pointFounded = new GLatLng(hebergementLat, hebergementLong);
					myMarkerManager.adressSearching = false;
				}
				else if (point.Placemark.length > 1)
				{
					if (debug) {GLog.write("Nombre d'adresse trouvées : "+point.Placemark.length);}
					var message = point.Placemark.size()+" localité trouvées : <br /><br />";
					for (var i = 0 ; i < point.Placemark.size() ; i++)
					{
						// Contient la commune détaillée sous la forme : Commune, Département, Région
						var communeDetaillee = myMarkerManager.construireAddressDetail(point.Placemark[i]).replace(/\<br \/\>/g,',');
						var communeCoords = point.Placemark[0].Point.coordinates[1]+'X'+point.Placemark[0].Point.coordinates[0];
						
						if (debug) {GLog.writeHtml("["+i+"] <b>"+communeDetaillee+"</b> (précision:"+point.Placemark[i].AddressDetails.Accuracy+")<br />"+point.Placemark[i].Point.coordinates[1]+"X"+point.Placemark[i].Point.coordinates[0]);}
						
						message += "["+parseInt(i+1)+"] Adresse : "+point.Placemark[i].address+"<br />";
						message += "["+parseInt(i+1)+"] Libellé : "+communeDetaillee+"<br />";
						message += "["+parseInt(i+1)+"] Coordonnées : "+communeCoords+"<br />";
						message += "["+parseInt(i+1)+"] Précision : "+point.Placemark[i].AddressDetails.Accuracy+"<br /><br />";
						
						// Si je trouve la chaine "Mayenne" dans communeDetaillee, je prends les coordonnées de ce placeMark
						if (communeDetaillee.indexOf("Mayenne",0) != -1 && hebergementLat == "" && hebergementLong == "")
						{
							hebergementLat = point.Placemark[i].Point.coordinates[1];
							hebergementLong = point.Placemark[i].Point.coordinates[0];
							load();
						}
						
					}
					//hebergementLat = point.Placemark[0].Point.coordinates[1];
					//hebergementLong = point.Placemark[0].Point.coordinates[0];
					//load();
					if (typeof(myMarkerManager._options.urlForCoordinatesUpdate) != "undefined")
					{
						var maRequete = new Ajax.Request(myMarkerManager._options.urlForCoordinatesUpdate+'&id_hebergement='+adressObj.id+'&message='+message+'&hazard='+Math.random());
					}
					
					myMarkerManager.pointFounded = false;
					myMarkerManager.adressSearching = false;
				}
			}
			debug = false;
		}
	);
	//return this.returnPointWhenSearchFinished(this);
	debug = false;
};


/**
* Fonction posant un timeout et retournant le point quand l'adresse est trouvée
* @param (MarkerManager) myMarkerManager : Objet courant, nécessaire pour pouvoir etre appelé dans un setTimeout
*/
MarkerManager.prototype.returnPointWhenSearchFinished = function(myMarkerManager)
{
	GLog.write('Appel de returnPointWhenSearchFinished, this.adressSearching:'+myMarkerManager.adressSearching);
	if (myMarkerManager.adressSearching == false)
	{
		GLog.write('this.adressSearching == false -> je retourne');
		clearTimeout(myMarkerManager.recheckSearchAdressTimeout);
		return myMarkerManager.pointFounded;
	}
	else
	{
		GLog.write('this.adressSearching != false -> je continue');
		myMarkerManager.recheckSearchAdressTimeout = setTimeout(function(){myMarkerManager.returnPointWhenSearchFinished(myMarkerManager);},200);
	}
};



/**
* Fonction de construction de libelle d'adresse
* @param (placeMark) placeMark : Objet Placemark dont on veut obtenir le libellé complet de l'adresse
* @return (String) : Libellé de l'adresse
*/
MarkerManager.prototype.construireAddressDetail = function (placeMark)
{
	var t_libelle = new Array();
	var libelle = '';
	if (debug) {GLog.write("Appel de construireAddressDetail ("+placeMark+")");}
	t_libelle = this.recupererAdressDetails(placeMark.AddressDetails, t_libelle);
	if (t_libelle.size() > 1)
	{
		for (var i = (t_libelle.size()-1) ; i >= 0 ; i--)
		{
			if (i == 0) {libelle += ', ';} // une virgule pour séparer le pays
			else if (i < (t_libelle.size()-1)) {libelle += '<br /> ';} // Retour à la ligne après chaque label
			libelle += t_libelle[i];
		}
	}
	// Si seul le pays a été trouvé je renvois l'adresse du géocoder
	else
	{
		libelle =  placeMark.address.replace(',','<br />');
	}
	if (debug) {GLog.writeHtml("Adresse récupérée : <b>"+libelle+"</b>");}
	return libelle;
};

/**
* Fonction retournant la String d'un objet enfant de l'attribut placeMark.AddressDetails (fonction récursive qui se réappelle si il existe encore des objets contenant des détails d'adresse)
* @param (Object) addressDetails : Objet enfant (à différents niveaux de profondeurs) de l'attribut placeMark.AddressDetails 
* @param (Array) t_libelle : Tableau contenant les différents libellés trouvés pour chaque profondeur
* @return (Array)  : Tableau contenant TOUS les différents libellés trouvés pour chaque profondeur
*/
MarkerManager.prototype.recupererAdressDetails = function (addressDetails, t_libelle)
{
	var debugRecupererAdressDetails=false;
	var objectFound = false;
	if (debugRecupererAdressDetails) {GLog.write("Appel de recupererAdressDetails ("+addressDetails+")");}
	for (var n in addressDetails)
	{
		if (debugRecupererAdressDetails) {GLog.write(n+" : "+addressDetails[n]+" (type:"+typeof(addressDetails[n])+")");}
		if (typeof(addressDetails[n]) == "object")
		{
			objectFound = true;
			if (debugRecupererAdressDetails) {GLog.write("Objet trouvé, appel récursif");}
			return this.recupererAdressDetails(addressDetails[n], t_libelle);
		}
		else if (typeof(addressDetails[n]) == "string")
		{
			t_libelle.push(addressDetails[n]);
			if (debugRecupererAdressDetails) {GLog.write("String trouvéé : '"+addressDetails[n]+"'");}
		}
	}
	if (objectFound == false)
	{
		if (debugRecupererAdressDetails) {GLog.write("Pas d'objet trouvé, libellé : '"+t_libelle+"'");}
		return t_libelle;
	}
};

/**
* Fonction créant une GIcon pour une catégorie et la stockant dans le tableau _categoriesIcons de la classe
* @param (Mixed) categorieID : Identifiant de la catégorie
* @param (String) categorieIconePath : URL de l'icone
* @param (Integer) categorieIconeWidth : Largeur de l'icone
* @param (Integer) categorieIconeHeight : Hauteur de l'icone
*/
MarkerManager.prototype.createCategorieIcon = function (categorieID, categorieIconePath, categorieIconeWidth, categorieIconeHeight)
{
	if (typeof(categorieIconePath) != 'undefined' && categorieIconePath != '')
	{
		this._categoriesIcons[categorieID] = new GIcon();
		this._categoriesIcons[categorieID].image=categorieIconePath;
		this._categoriesIcons[categorieID].iconSize=new GSize(categorieIconeWidth, categorieIconeHeight);
		this._categoriesIcons[categorieID].iconAnchor=new GPoint(parseInt(categorieIconeWidth)/2, parseInt(categorieIconeHeight)/2);
		this._categoriesIcons[categorieID].infoWindowAnchor = new GPoint(parseInt(categorieIconeWidth)/2, 5);
	}
	else if (typeof(this._defaultIcon) == 'object')
	{
		this._categoriesIcons[categorieID] = this._defaultIcon;
	}
	// Sinon, icone par défaut
	else
	{
		this._categoriesIcons[categorieID] = G_DEFAULT_ICON;
	}
};

