function tx_decgmaps_manager(config, mapId, poiListURL){
	this.config = config;
	this.mapId = mapId;
	this.poiListURL = poiListURL;
	return this;
}

tx_decgmaps_manager.prototype = {
	VERSION: "0.0.1",
	config: null,
	mapId: "",
	poiListURL: "",
	
	categories: {},
	
	gmap: null,
	mng: null,
	
	markersData: null,
	
	modules: {},
	
	LL: {},
	
	/**
	 * Lance l'affichage de la carte
	 */
	start: function(){
		if(!GMap2 || !MarkerManager) return false;
		
		for(var i in this.modules){
			try{
				this.modules[i].init();
			} catch(e){}
		}
		
			//définition des types de cartes à charger
		var opts = {};
		opts.mapTypes = [];
		for(var i = 0; i < this.config.mapTypes.length; i++){
			opts.mapTypes.push(eval(this.config.mapTypes[i]));
		}
			//création de la carte
		this.gmap = new GMap2(jQuery("#"+this.mapId+"-map").get(0), opts);
		this.setControls();
		this.gmap.setCenter(new GLatLng(parseFloat(this.config.defaut.lat), parseFloat(this.config.defaut.lng)), parseInt(this.config.defaut.zoom));
		
			//création du MarkerManager
		this.mng = new MarkerManager(this.gmap);
		this.loadMarkers();
		
		for(var i in this.modules){
			try{
				this.modules[i].start();
			} catch(e){}
		}
	},
	
	/**
	 * Charge le XML des markers
	 */
	loadMarkers: function(){
		var ref = this;
		jQuery.get(this.poiListURL, null, function(data){ ref.loadMarkersData(data);});
	},
	
	/**
	 * Charge le XML des marqueurs
	 */
	loadMarkersData: function(data){
		this.markersData = jQuery(data).find("poiList poi");
		this.addMarkersToManager();
	},
	
	/**
	 * Ajoute l'ensemble des markers au manager.
	 */
	addMarkersToManager: function(){
		var mark;
		var markers = [];
		var ref = this;
		this.markersData.each(function(){
			mark = ref.makeMarker(jQuery(this));
			if(mark != null) markers.push(mark);
		});
		
		this.mng.clearMarkers();
		this.mng.addMarkers(markers, parseInt(this.config.showMarkersOnZoomLevel));
		this.mng.refresh();
	},
	
	/**
	 * Crée un marker GMap à partir d'un noeud XML
	 * @param	node	Objet jQuery du noeud XML du POI
	 * @return	GMarker
	 */
	makeMarker: function(node){
		var mark = new GMarker(new GLatLng(node.attr("lat"), node.attr("lng")), {
			icon: this.categories['cat' + node.attr("cat")],
			title: node.text(),
			clickable: true
		}); 
		mark.iwURL = node.attr("href");

		var ref = this;
		GEvent.addListener(mark, "click", function() {
			ref.loadInfoWindowContent(mark);
		});
		return mark;
	},
	
	/**
	 * Ajoute les contrôles définis dans la configuration à la carte
	 */
	setControls: function(){
		var ctrl;
		var pos;
		for(var i in this.config.controles){
			ctrl = eval('new '+i+'()');
/*			if(this.config.controles[i].x != null && this.config.controles[i].y != null){
				pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(this.config.controles[i].x, this.config.controles[i].y));
			} else pos = ctrl.getDefaultControlPosition();*/
			this.gmap.addControl(ctrl);//, pos);
		}
	},
	
	/**
	 * Charge le contenu de l'infobulle
	 */
	loadInfoWindowContent: function(marker){
		var ref = this;
		var mark = marker;
		jQuery.get(marker.iwURL, null, function(data){
			ref.setInfoWindow(mark, data);
		});
	},
	
	/**
	 * Affiche l'infobulle
	 */
	setInfoWindow: function(marker, data){
		var tabs = [];
		jQuery(data).find("infoWindowTabs tab").each(function(){
			tabs.push(new GInfoWindowTab(jQuery(this).find("name").text(), jQuery(this).find("content").text()));
		});
		
		marker.openInfoWindowTabsHtml(tabs);
		
			//ajout des évènements
		var ref = this;
		jQuery(data).find("infoWindowTabs event").each(function(){
			var func = jQuery(this).text();
			if(func != ""){
				GEvent.addListener(marker, jQuery(this).attr("name"), function(){ 
					try{ 
						eval('ref.' + func + '();');
					} catch(e){}
				});
			}
		});
	},
	
	/**
	 * Crée l'icône correspondant à la catégorie
	 */
	addCat: function(id, config){
		if(config != null){
			var icon = new GIcon(G_DEFAULT_ICON);
			var o;
			var d1;
			var d2;
			for(var i in config){
				switch(i){
					case 'iconSize':
					case 'shadowSize':
					case 'dragSize':
						if(config[i].length == 2){
							d1 = parseInt(config[i][0]);
							d2 = parseInt(config[i][1]);
							if(d1 > 0 && d2 > 0){
								o = new GSize(d1, d2);
								icon[i] = o;
							}
						}
						break;
					
					case 'iconAnchor':
					case 'infoWindowAnchor':
					case 'dragCrossAnchor':
						if(config[i].length == 2){
							d1 = parseInt(config[i][0]);
							d2 = parseInt(config[i][1]);
							o = new GPoint(d1, d2);
							icon[i] = o;
						}
						break;
					
					case 'maxHeight':
						icon[i] = parseInt(config[i]);
						break;
						
					default:
						if(config[i] != "") icon[i] = config[i];
						break;
				}
			}
		} else var icon = G_DEFAULT_ICON;
		
		this.categories['cat' + id] = icon;
	},
	
	/**
	 * Ajoute un module à l'objet courant
	 */
	addModule: function(name, object, config){
		this.modules[name] = object;
		this.modules[name].ref = this;
		this.modules[name].config = config;
	},
	
	showVersion: function(){
		window.alert("Version " + this.VERSION);
	}

};