// Instancie un objet OsCarto avec le div spécifié utilisé pour afficher la carte google
function OsCarto( mapDivId )
{
	// Propriété indiquant l'identifiant du div utilisé pour afficher la carte google
	this.map_div_id = mapDivId;
	// Propriété indiquant si la carte google a déjà été chargée ou non
	this.map_loaded = false;
	// Propriété contenant l'icône à utiliser pour les marqueurs
	this.marqueurs_icones = new Array();
	// Propriété contenant les marqueurs placés sur la carte
	this.marqueurs = new Array();
	// Propriété contenant les controles à ajouter 
	this.controles = new Array();
	// Propriété contenant les types de map à activer 
	this.maptypes = new Array();
	// Propriété contenant le types de map à activer par défaut
	this.maptype_defaut = null;
	// Propriété contenant un itinéraire éventuel
	this.directions = null;
	// Propriété permettant de stocker le GLatLngBounds de la carte
	this.mapBounds = null;
	// Propriété permettant de stocker le dernier zoom max spécifié
	this.mapZoomMax = null;
	// Propriété permettant de stocker le centre de la carte
	this.mapCenter = null;	
	// Url de récupération des flux json
	this.json_url = null;
	// Propriété contenant les sources json utilisées
	this.json_sources = new Array();
	// Propriété permettant d'indexer les sources json utilisées
	this.json_sources_index = new Array();
	// Gestion de regroupement d'items
	this.marqueurs_familles = new Array();
	// Gestion des descriptions html des marqueurs
	this.marqueurs_html = new Array();
	// Callback appelée à la fin de l'initialisation du flux json initial
	this._json_callbackInitOk = null;
	// Callback appelée à la fin du chargement des sources json
	this._json_callbackLoadOk = null;
}
// Méthode de chargement de la carte google dans le div spécifié. A utiliser quand la page a été chargée (pour avoir accès au div)
OsCarto.prototype.initialiser = function ()
{
	if ( this.map_loaded ) return;
	if ( GBrowserIsCompatible() ) 
	{	
		this.map_div = document.getElementById( this.map_div_id );
		this.map = new GMap2( this.map_div );
		for( i=0; i < this.maptypes.length; i++ ) 
			this.map.addMapType( this.maptypes[i] );
		var maptypeASupp = new Array();
		for( i=0; this.maptypes.length > 0 && i < this.map.getMapTypes().length; i++ )
		{
			var existeMapType = false;
			for( j=0; j < this.maptypes.length && !existeMapType; j++ ) existeMapType = this.maptypes[j].getName() == this.map.getMapTypes()[i].getName();
			if( !existeMapType ) maptypeASupp.push( this.map.getMapTypes()[i] );
		}
		for( asupp = maptypeASupp.pop(); asupp != null; asupp = maptypeASupp.pop() ) this.map.removeMapType( asupp );
		if( this.maptype_defaut ) 
			this.map.setMapType( this.maptype_defaut );
		for( i=0; i < this.controles.length; i++ )
			this.map.addControl( this.controles[i] );
		this.map_loaded = true;	
	}
}
// Méthode de chargement de la carte google dans le div spécifié. A utiliser quand la page a été chargée (pour avoir accès au div)
OsCarto.prototype.json_initialiser = function ( jsonUrl, xmlUrl, callbackInitOk, callbackLoadOk )
{
	if ( this.map_loaded ) return;
	if ( GBrowserIsCompatible() ) 
	{	
		this.map_div = document.getElementById( this.map_div_id );	
		this.map = new GMap2( this.map_div );
		this.json_url = jsonUrl;		
		this._json_callbackInitOk = callbackInitOk;
		this._json_callbackLoadOk = callbackLoadOk;
		// On charge le fichier listant les différentes sources json controlant la carte
		$.ajax( { url:this.json_url+"/jsonp.aspx?px="+escape(xmlUrl), dataType:"jsonp", success:_OsCarto_json_initialiser_callback } );				
	}
}
// Méthode de chargement de la carte google dans le div spécifié. A utiliser quand la page a été chargée (pour avoir accès au div)
OsCarto.prototype.json_charger = function ( ref ) 
{
	$.ajax( { url:this.json_url+"/jsonp.aspx?px="+escape(this.json_sources[ref].Url), dataType:"jsonp", success:_OsCarto_json_charger_callback });
}
// Méthode appelée une fois le flux json récupéré
_OsCarto_json_initialiser_callback = function ( obj )
{
	carto.map_loaded = true;
	for( i=0; i < obj.GMapTypesActif.length; i++ ) { carto.map.addMapType( eval( obj.GMapTypesActif[i].GMapType ) ) };
	for( i=0; i < obj.GMapTypesInactif.length; i++ ) { carto.map.removeMapType( eval( obj.GMapTypesInactif[i].GMapType ) ); }
	if( obj.GMapTypesDefaut != null && obj.GMapTypesDefaut != '' ) carto.map.setMapType( eval( obj.GMapTypesDefaut ) );
	for( i=0; i < obj.GControls.length; i++ ) { carto.map.addControl( eval( obj.GControls[i].GControl ) ) };
	if( obj.Centre ) { carto.centrer2( obj.Centre.Latitude, obj.Centre.Longitude, obj.Centre.Zoom ); }
	for( i=0; i < obj.Sources.length; i++ ) { carto.json_sources[ obj.Sources[i].Ref ] = obj.Sources[i]; carto.json_sources_index.push( obj.Sources[i].Ref ); }
	for( i=0; i < obj.GIcon.length; i++ ) { carto.JsonGIcon( obj.GIcon[i].Ref, obj.GIcon[i].Url, obj.GIcon[i].UrlShadow, obj.GIcon[i].AncreX, obj.GIcon[i].AncreY, obj.GIcon[i].AncreInfoX, obj.GIcon[i].AncreInfoY ); }
	_OsCarto_json_charger_auto_callback( 0 );
	if( carto._json_callbackInitOk != null ) carto._json_callbackInitOk();	
}
// Méthode récursive de chargement des sources jason à l'initialisation
_OsCarto_json_charger_auto_callback = function( index )
{
	if( index < carto.json_sources_index.length )
	{
		if( carto.json_sources[ carto.json_sources_index[ index ] ].Defaut == 1 )
			carto.json_charger( carto.json_sources_index[ index ] );
		_OsCarto_json_charger_auto_callback( index+1 );
	}		
}
// Méthode appelée une fois le flux json récupéré
_OsCarto_json_charger_callback = function ( obj )
{
	for(var i=0;i<obj.Items.length;i++) 	
	{			
		var polyline = null;
		var marker = carto.ajouterMarqueur( obj.Items[i].Id, parseFloat(obj.Items[i].Latitude), parseFloat(obj.Items[i].Longitude), obj.Items[i].description, carto.marqueurs_icones[ obj.Items[i].Icone ], obj.Items[i].Titre );
		if( obj.Items[i].Polyline != null && obj.Items[i].Polyline != 'undefined' )
		{
			var coords = obj.Items[i].Polyline.coordinates.match(/\d+(\.\d+)?/g);
			var polyLatLng = new Array();
			for( j=0; j < coords.length; j+=3) polyLatLng[ j / 3 ] = new GLatLng( coords[j+1], coords[j] );
			polyline = new GPolyline( polyLatLng, obj.Items[i].Polyline.LineStyle.color, obj.Items[i].Polyline.LineStyle.width, obj.Items[i].Polyline.LineStyle.opacity );
			polyline._marker = marker;
			GEvent.addListener( polyline, "click", function( latlng ) { this._marker.openInfoWindowHtml( this._marker._html ); } );
			carto.map.addOverlay(polyline);
		}		
		if( obj.Items[i].Famille && obj.Items[i].Famille.Id && obj.Items[i].Famille.Id != '' )
		{
			if( carto.marqueurs_familles[ obj.Items[i].Famille.Id ] == null )
				carto.marqueurs_familles[ obj.Items[i].Famille.Id ] = new Array();
			if( polyline != null ) carto.marqueurs_familles[ obj.Items[i].Famille.Id ].push( polyline );
			if( marker != null ) carto.marqueurs_familles[ obj.Items[i].Famille.Id ].push( marker );			
		}		
	}
	if( carto._json_callbackLoadOk != null ) carto._json_callbackLoadOk( obj.Ref );
}
// Méthode permettant l'affichage / masquage d'une famille de marqueurs
OsCarto.prototype.checkFamille = function ( checked, familleid ) 
{ 
	var familles = this.marqueurs_familles[ familleid ];
	if( familles != null )
		for(i=0;i<familles.length; i++ )
			if( checked ) familles[i].show(); else familles[i].hide();
}
// Méthode renvoyant l'état de visibilité d'une famille de marqueurs
OsCarto.prototype.estFamilleVisible = function( familleid ) 
{
	var familles = this.marqueurs_familles[ familleid ];
	if( familles != null && familles.length > 0 )
		return !familles[0].isHidden();
	return false;
}
// Méthode de recentrage de la carte google  en fonction des coordonnées spécifiées
OsCarto.prototype.centrer = function ( LatitudeMin, LatitudeMax, LongitudeMin, LongitudeMax, ZoomMax)
{
	if( this.map_loaded )
	{		
		var dtLatitude = (LatitudeMax - LatitudeMin) / 8;
		var dtLongitude = (LongitudeMax - LongitudeMin) / 8;
		this.mapBounds = new GLatLngBounds( new GLatLng( LatitudeMin - dtLatitude, LongitudeMin - dtLongitude ), new GLatLng( LatitudeMax + dtLatitude, LongitudeMax + dtLongitude) );
		this.mapZoomMax = ZoomMax;
		this.recentrer();		
	}
}
// Méthode de recentrage de la carte google  en fonction des coordonnées spécifiées
OsCarto.prototype.centrer2 = function ( Latitude, Longitude, Zoom)
{
	if( this.map_loaded )
	{
		this.mapCenter = new GLatLng( Latitude, Longitude );
		this.mapZoomMax = Zoom;
		this.recentrer();
	}
}
// Méthode permettant le recentrage de la carte google en fonction des bounds et du zoommax de la carte
OsCarto.prototype.recentrer = function () 
{ 
	if( this.map_loaded )
	{
		this.map.checkResize();
		if( this.mapCenter != null )
			this.map.setCenter( this.mapCenter, this.mapZoomMax );
		else
		{
			var zoom = this.map.getBoundsZoomLevel( this.mapBounds );
			this.map.setCenter( this.mapBounds.getCenter(), zoom > this.mapZoomMax ? this.mapZoomMax : zoom );
		}
		this.map.checkResize();	
	}
}
// Méthode permettant de masquer le div contenant la carte
OsCarto.prototype.masquer = function()
{
	document.getElementById( this.map_div_id ).style.display = 'none';
}
// Méthode de création de marqueurs sur la carte
OsCarto.prototype.ajouterMarqueur = function ( cle, Latitude, Longitude, Html, Icone, Titre ) 
{
	var marker = new GMarker( new GLatLng( Latitude, Longitude ), { title:Titre, icon:Icone } );
	marker._html = Html;
	marker.bindInfoWindowHtml( Html );
	this.map.addOverlay(marker);
	if( cle ) { this.marqueurs[ cle ] = marker; this.marqueurs_html[ cle ] = Html; }
	return marker;
}
// Méthode de suppression des marqueurs ajoutés à la carte
OsCarto.prototype.supprimerMarqueurs = function ()
{
	this.map.clearOverlays();
	while(this.marqueurs.length > 0 ) { this.marqueurs.pop(); this.marqueurs_html.pop(); }
	while(this.marqueurs_familles.length > 0 ) { this.marqueurs_familles.pop(); }
}
// Permet de faire afficher la bulle html du marqueur spécifié
OsCarto.prototype.ouvrirMarqueurHtml = function( cle, Html )
{
	this.marqueurs[ cle ].openInfoWindowHtml( Html );
}
// Permet de faire afficher la bulle html du marqueur spécifié
OsCarto.prototype.ouvrirInfoHtml = function( cleMarqueur )
{
	this.marqueurs[ cleMarqueur ].openInfoWindowHtml( this.marqueurs_html[ cleMarqueur ] );
}
// Méthode permettant de récupérer une icone pour les marqueurs
OsCarto.prototype.OsGIcon = function ( nom, larg, haut, slarg)
{
	if( this.marqueurs_icones[ larg + "x" + haut + "-" + nom ]  )
		return this.marqueurs_icones[ larg + "x" + haut + "-" + nom ];
	var icon = new GIcon();
	icon.image = "osico/marker/marker" + larg + "x" + haut + "-" + nom + ".png";
	icon.shadow = "osico/marker/marker" + larg + "x" + haut + "-shadow.png";
	icon.imageSize = new GSize(larg, haut);
	icon.shadowSize = new GSize(slarg, haut);
	icon.iconAnchor = new GPoint(larg >> 1, haut >> 1);
	icon.infoWindowAnchor = new GPoint(larg >> 1, haut >>1);
	this.marqueurs_icones[ larg + "x" + haut + "-" + nom ] = icon;
	return icon;
}
// Méthode permettant de récupérer une icone pour les marqueurs
OsCarto.prototype.JsonGIcon = function( ref, url, urlshadow, ancrex, ancrey, ancreinfox, ancreinfoy )
{
	if( this.marqueurs_icones[ ref ]  )
		return this.marqueurs_icones[ ref ];
	var icon = new GIcon();
	icon.image = url;
	icon.shadow = urlshadow;
	icon.iconAnchor = new GPoint( ancrex != null ? ancrex : 0, ancrey != null ? ancrey : 0 );
	icon.infoWindowAnchor = new GPoint( ancreinfox != null ? ancreinfox : 0, ancreinfoy != null ? ancreinfoy : 0 );
	this.marqueurs_icones[ ref ] = icon;
	return icon;
}

// Méthode permettant de déplacer la carte google dans un autre élément
OsCarto.prototype.deplacer = function ( idEltDest )
{	
	this.map_div.parentNode.removeChild( this.map_div );
	document.getElementById( idEltDest ).appendChild( this.map_div );
}
// Méthode permettant de (re)définir un itinéraire
OsCarto.prototype.setDirections = function( elt, fromAddress, toAddress, locale, avoidHighways, erreurCallback, travelMode )
{
	if( this.directions == null )
	{
		this.directions = new GDirections( this.map, elt );
		GEvent.addListener( this.directions, "error", erreurCallback );
	}
    this.directions.load("from: " + fromAddress + " to: " + toAddress, { "locale": locale, "avoidHighways": avoidHighways, "travelMode": travelMode ? parseInt( travelMode) : G_TRAVEL_MODE_DRIVING });
}
// Objet permettant d'ajouter un controle sur la carto
function OsCartoDivCtrl( defaultPosition, obj, clickCallBack )
{
	this.defaultPosition_ = defaultPosition;
	this.obj_ = obj;
	this.clickCallback_ = clickCallBack;
}
// L'objet divctrl hérite de GControl
OsCartoDivCtrl.prototype = new GControl();
// Initialisation du controle avec création d'un div comme conteneur du controle
OsCartoDivCtrl.prototype.initialize = function( map ) {
	var container = document.createElement("div");
    container.appendChild( this.obj_ );
    GEvent.addDomListener( this.obj_, "click", this.clickCallback_ );
    map.getContainer().appendChild( container );
    return container;
}
// Surcharge de la méthode dans GControl pour indiquer la position par défaut du controle
OsCartoDivCtrl.prototype.getDefaultPosition = function() { return this.defaultPosition_; }

// Objet permettant d'ajouter un div en overlay sur la carto
function OsCartoDivOverlay( latlng, obj, pane ) 
{
	this.latlng_ = latlng;
	this.obj_ = obj;
	this.pane_ = pane;
}
// L'objet hérite de GOverlay
OsCartoDivOverlay.prototype = new GOverlay();
// Initialisation du div avec création d'un autre div en position absolue comme conteneur
OsCartoDivOverlay.prototype.initialize = function( map ) {
    var div = document.createElement("div");
    div.style.position = "absolute";    
    div.appendChild( this.obj_ );
    map.getPane( this.pane_ ).appendChild( div );
    this.div_ = div; 
    this.map_ = map;     
    this.obj_.zIndex = 0;
}  
// Surcharge 
OsCartoDivOverlay.prototype.remove = function() { this.div_.parentNode.removeChild(this.div_); }
// Surcharge 
OsCartoDivOverlay.prototype.copy = function() { return new divobjet(); }
// Surcharge 
OsCartoDivOverlay.prototype.redraw = function(force) {
	if (!force) return;
    var c1 = this.map_.fromLatLngToDivPixel( this.latlng_ );
    this.div_.style.left = c1.x + "px";
    this.div_.style.top = c1.y + "px";
}
// Permet de placer le div au premier plan
OsCartoDivOverlay.prototype.tofront = function() {
	this.remove( ); 
	this.map_.getPane( this.pane_ ).appendChild( this.div_ );	
}
// Masque le div
OsCartoDivOverlay.prototype.hide = function() { this.obj_.style.display = "none"; }
// Affiche le div
OsCartoDivOverlay.prototype.show = function() { this.obj_.style.display = "block"; }
// Attribue la classe css au div
OsCartoDivOverlay.prototype.setClass = function( classname ) { this.obj_.className = classname; }

