MyGMap = function(id_div_carte) {
	this.filtresCamp = new Array();
	this.templateContenuBulle = "NOM : ${data.nom}<br/>ETOILE : ${data.rate}<br/>REGION : ${data.region}<br/>PHOTO : ${data.photo}<br/>NUM CAMP ${data.num_camp}<br/>";
    this.mapCircle = null;
    this.div_carte = document.getElementById(id_div_carte);
    this.gmap = new GMap2(this.div_carte);
	this.gmap.addControl(new GMapTypeControl());
	this.gmap.addMapType(G_PHYSICAL_MAP);
	this.gmap.setMapType(G_PHYSICAL_MAP);
	this.gmap.enableScrollWheelZoom(); 
    this.geoXml = new GeoXml(this);
    this.markerCamps = new Array();
    this.defaultStyle = new GIcon();
    this.SetCenter = function(latitude, longitude,zoom) {
		this.gmap.setCenter(new GLatLng(latitude,longitude),zoom);
    }
    this.GoBestCenter = function() {
        var bou = new GLatLngBounds();
        for (var i = 0; i < this.markerCamps.length; i++) {
            var m = this.markerCamps[i].marker;
            bou.extend(m.getLatLng());
        }
        if (this.markerCamps.length == 1)
            this.gmap.setCenter(this.markerCamps[0].marker.getLatLng(), 7);
        else
            this.gmap.setCenter(bou.getCenter(), this.gmap.getBoundsZoomLevel(bou));
    }
    this.CreateDescription = function(donnee) {
		
		return this.templateContenuBulle.process({data:donnee});
    }
    this.AddMarker = function(marker, data) {
        this.markerCamps.push(new MarkerCamp(marker, data));
        this.gmap.addOverlay(marker);
    }
    this.RetourDisplayDataXML = function() {
        this.GoBestCenter();
    }
    this.SetDefaultIcon = function(url) {
        this.defaultStyle = this.geoXml.makeIcon(url);
    }
	this.EnableSelectionCercle = function(id_champ_rayon,id_tb_latitude,id_tb_longitude){		
		this.longitude = document.getElementById(id_tb_longitude);
		this.latitude = document.getElementById(id_tb_latitude);
		InitMarkerCentre.call(this);
		var that = this;
		GEvent.addListener(this.gmap, 'click', 
			function (overlay, point){
				if(!overlay){
					if(!that.markerCenter){
						that.markerCenter = new GMarker(point,{draggable:true});	
						that.gmap.addOverlay(that.markerCenter);
					}
					else{
						that.markerCenter.setLatLng(point);
					}
					that.mapCircle.UpdateCircle();
					setLatLng.call(that,point);
				}
			}
		);
        GEvent.addListener(this.gmap, 'move', 
			function(){
				that.mapCircle.dessineCadre();
			}
		);
		
		this.mapCircle = new MapCircle(this,this.markerCenter,id_champ_rayon);		
	}
	function InitMarkerCentre(){
		var point = new GLatLng(this.latitude.value,this.longitude.value);
		if(!this.markerCenter){
                this.markerCenter = new GMarker(point,{draggable:true});
                var that = this; 
                GEvent.addListener(this.markerCenter , 'drag', 
					function(){
						that.mapCircle.UpdateCircle();
						setLatLng.call(that,this.getPoint());
					}
				);  
                this.gmap.addOverlay(this.markerCenter);
        }
        else{
            setLatLng.call(this,point);
        }
	}
	function setLatLng (point){
		if(this.longitude && this.latitude){
			this.latitude.value = point.lat();
			this.longitude.value = point.lng();
		}
	}
	this.AddFiltre = function(filtre){
		this.filtresCamp.push(filtre);
		this.filtresCamp[filtre.cham_filtre] = filtre;
	}
	this.Filtre = function(){
		for(var i = 0;i<this.markerCamps.length;i++){			
			this.markerCamps[i].montrer();
		}
		for(var i = 0;i<this.filtresCamp.length;i++){
			for(var j = 0;j<this.markerCamps.length;j++){
				if(!this.filtresCamp[i].EstOK(this.markerCamps[j]))
					this.markerCamps[j].cacher();
			}
		}
	}
}

//cette classe se charge de charger la carte a partir d'un fichier kml / json
GeoXml = function(myGMap) {
    this.myGMap = myGMap;
    this.stylesGMap = [];
    function manageStyle(styles) {
        var styles_temps = makeArrayIfNot(styles);
        for (var i = 0; i < styles_temps.length; i++) {
            var sid = styles_temps[i].id;
            if (sid) {
                var href = styles_temps[i].iconstyle.icon.href;
                if (!!href)
                    this.stylesGMap["#" + sid] = this.makeIcon(href);
            }
        }
    }
    function ImageSize(src) {
        var newImg1 = new Image();
        newImg1.src = src;
        return { height: newImg1.height, width: newImg1.width };
    }
    this.makeIcon = function(href) {
        var tempstyle = new GIcon();
        var taille = ImageSize(href);
        var width_icon;
        var height_icon;
        if (taille.width == 0 || taille.height == 0) {
            taille = { width: 64, height: 64 };
        }
        //cas ou je done une largeur mais que ça n'agrandi pas l'icone
        //  if (this.opts.width_icon && this.opts.width_icon < taille.width) {
        //si on a pas pu renseigner les dimension de l'icone			
        width_icon = 10;
        height_icon = ((taille.height * width_icon) / taille.width);
        /* }
        else {
        width_icon = taille.width;
        height_icon = taille.height;
        }*/

        tempstyle.infoWindowAnchor = new GPoint(width_icon / 2, height_icon / 2);
        tempstyle.iconSize = new GSize(width_icon, height_icon);
        tempstyle.iconAnchor = new GPoint(width_icon / 2, height_icon / 2);
        tempstyle.imageMap = [0, 0, (width_icon - 1), 0, (height_icon - 1), (width_icon - 1), 0, (height_icon - 1)];
        tempstyle.image = href;
        tempstyle.shadow = "";
        return tempstyle;
    }
	
    function makeArrayIfNot(objet) {

        if (!objet.length) {
            var array_temp = new Array();
            array_temp.push(objet);
            return array_temp;
        }
        return objet;

    }
    function creerPlacemarks(node) {
        var node_temp = makeArrayIfNot(node);
        var len = node_temp.length;
        for (i = 0; i < len; i++) {
            creerMarker.call(this, node_temp[i]);
        }
    }
    function creerMarker(marker) {
        var coordonnees = marker.point.coordinates.split(',');       
        var desc = (marker.description) ? marker.description : "";
        var style = (marker.styleurl) ? this.stylesGMap[marker.styleurl] : this.myGMap.defaultStyle;
        var point = new GLatLng(parseFloat(coordonnees[1]), parseFloat(coordonnees[0]));
        var data = (marker.extendeddata) ? marker.extendeddata : {};
        var gMarker = new GMarker(point, { icon: style,title:''});/* ,zIndexProcess:
			function (marker,b) {
				return GOverlay.getZIndex(marker.getPoint().lat()) + marker.importance*1000000;
			}}
		);	*/
		gMarker.getIcon().shadow = "";
		gMarker.title = "";
        var desc = this.myGMap.CreateDescription(eval("("+data+")"));
        
        GEvent.addListener(gMarker, "click", function() {
            gMarker.openInfoWindow(desc);
        });
		this.myGMap.AddMarker(gMarker, data);
    }
    this.DisplayData = function(url) {
        var util = new UtilAjax();
        var data = util.GetXmlDataToJson(url);
        if (!data) return;
        var root = data.kml;
        var placemarks = [];
        if (root.document.style) {
            manageStyle.call(this, root.document.style);
        }
        creerPlacemarks.call(this, root.document.placemark);
        this.myGMap.RetourDisplayDataXML();
    }

}
//cette classe se charge d'afficher une cercle sur la carte
MapCircle = function(mygmap,marker_centre, id_champ_rayon) {
	this.color_ligne = "#000000";

	this.mygmap = mygmap;
	this.marker_centre = marker_centre;
	this.rayon = document.getElementById(id_champ_rayon);
	function getRayon(){
		if(this.rayon)
			return this.rayon.value * 2;
		return 100;
	}
	function getGMap(){
		return this.mygmap.gmap;
	}
	// -Encode a signed number in the encode format.
	function encodeSignedNumber(num) {
		var sgn_num = num << 1;

		if (num < 0) {
			sgn_num = ~(sgn_num);
		}

		return(encodeNumber(sgn_num));
	}

	//- Encode an unsigned number in the encode format.
	function encodeNumber(num) {
		var encodeString = "";

		while (num >= 0x20) {
			encodeString += (String.fromCharCode((0x20 | (num & 0x1f)) + 63));
			num >>= 5;
		}

		encodeString += (String.fromCharCode(num + 63));
		return encodeString;
	}
	function createPointForEncode(lat,lon,zoom){
		return {Latitude:lat,Longitude:lon,Level:zoom};
	}
	function createEncodingsPoints(points) {
		var encoded_points = "";
		var plat = 0;
		var plng = 0;
		for(i = 0; i < points.length; ++i) {
			var point = points[i];
			var lat = point.Latitude;
			var lng = point.Longitude;
			var late5 = Math.floor(lat * 1e5);
			var lnge5 = Math.floor(lng * 1e5);
			dlat = late5 - plat;
			dlng = lnge5 - plng;
			plat = late5;
			plng = lnge5;
			encoded_points += encodeSignedNumber(dlat) + encodeSignedNumber(dlng);
		}	
		return encoded_points ;
	}
	function createEncodingsLevel(points){
		var encoded_levels = "";
		for(i = 0; i < points.length; ++i) {	
			encoded_levels += "P";
		}
		return encoded_levels;
	}
	function getTabFramePoints(){
		var zoom = getGMap.call(this).getZoom();
		var sw = getGMap.call(this).getBounds().getSouthWest();
		var ne = getGMap.call(this).getBounds().getNorthEast();
		var x_min = sw.lng();
		var x_max = ne.lng();
		var y_min = sw.lat();
		var y_max = ne.lat();
		var cadreLine = new Array();
		cadreLine.push(createPointForEncode(y_max,x_max,zoom));
		cadreLine.push(createPointForEncode(y_max,x_min,zoom));
		cadreLine.push(createPointForEncode(y_min,x_min,zoom));
		cadreLine.push(createPointForEncode(y_min,x_max,zoom));
		cadreLine.push(createPointForEncode(y_max,x_max,zoom));
		return cadreLine;
	}
	function dessineCercle(latitude,longitude,rayon){
		var normalProj = G_NORMAL_MAP.getProjection();	
	    var zoom = getGMap.call(this).getZoom();
	    var centerPt = normalProj.fromLatLngToPixel(this.marker_centre.getPoint(), zoom);
	    var latRadius = this.marker_centre.getLatLng().lat()+getRayon.call(this)/111;
	    var radiusPt = normalProj.fromLatLngToPixel(new GLatLng(latRadius,this.marker_centre.getLatLng().lng()),zoom);	   
	    var circlePoints = Array();
	    var circlePoints2 = Array();
	    with (Math) {
            var radiusDist = floor(sqrt(pow((centerPt.x-radiusPt.x),2) + pow((centerPt.y-radiusPt.y),2)));  
            radiusB = radiusDist - (min(255,radiusDist) / 2) * 1;
            for (var a = 10 ; a < 181 ; a+=10 ) {
                var aRad = a*2*(PI/180);
                y = centerPt.y + radiusB * sin(aRad)
                x = centerPt.x + radiusB * cos(aRad)
                var l = normalProj.fromPixelToLatLng( new GPoint(x,y), zoom);
                var p2 = createPointForEncode(l.lat(),l.lng(),zoom) ;
                circlePoints2.push(p2);
            }
            circlePoints2.push(circlePoints2[0]);
            var framePoints = getTabFramePoints.call(this);	
            this.parameterCircle =    {polylines: [
                    {//polilyne du cadre
                        points: createEncodingsPoints(framePoints), 
                        levels:createEncodingsLevel(framePoints),
                        color:this.color_ligne,
                        opacity: 1,
                        weight: 2,
                        numLevels: 18,
                        zoomFactor: 2
                    },	     
                    {//polilyne du cercle
                        points:createEncodingsPoints(circlePoints2) ,
                        levels:createEncodingsLevel(circlePoints2),
                        color: this.color_ligne,
                        opacity: 1,
                        weight: 4,
                        numLevels: 18,
                        zoomFactor: 2
                    }
                ],
                fill: true,
                color: this.color_ligne,
                opacity: 0.2,
                outline: true
            };
            this.dessineCadre();
	    }
	}
	function setEncodedPolygon(){
		if(this.polygoneCercle){
			getGMap.call(this).removeOverlay(this.polygoneCercle);
		}
		this.polygoneCercle = new GPolygon.fromEncoded(this.parameterCircle);
		getGMap.call(this).addOverlay(this.polygoneCercle);  
		var gmap = getGMap.call(this);
		GEvent.addListener(this.polygoneCercle, 'click',
			function(latlng){
				 GEvent.trigger(this.gmap, "click",null,latlng);  
			}
		);
	}
	this.dessineCadre = function(){
		if(this.parameterCircle && this.parameterCircle.polylines){
			var framePoints = getTabFramePoints.call(this);
			var points1 = createEncodingsPoints(framePoints);
			var level1 = createEncodingsLevel(framePoints);    
			this.parameterCircle.polylines[0] = 
					{points:points1, levels:level1,
						color: this.color_ligne,
						 opacity: 1,
						 weight: 2,
						 numLevels: 18,
						 zoomFactor: 2};				
			setEncodedPolygon.call(this);  
		}
	}
    this.UpdateCircle = function() {
		if(this.marker_centre)
			dessineCercle.call(this,this.marker_centre.getLatLng().lat(),this.marker_centre.getLatLng().lng(),getRayon.call(this));
    }
}

//cette classe contient les informations sur un camping et le marker qui lui est lié

MarkerCamp = function(markerGMap, infos_camp) {
    this.marker = markerGMap;
    this.infos = eval("("+infos_camp+")");;
    this.montrer = function() {
		this.marker.show();
    }
    this.cacher = function() {		
		this.marker.hide();
    }
}
UtilAjax = function() {
    this.GetXmlDataToJson = function(url) {
        if (window.XMLHttpRequest) {
            AJAX = new XMLHttpRequest();
        } else {
            AJAX = new ActiveXObject("Microsoft.XMLHTTP");
        }
        if (AJAX) {
            AJAX.open("GET", url, false);
            AJAX.send(null);
            return xml2json.parser(AJAX.responseText);
        } else {
            return false;
        }
    }
}
FiltreCamp = function(champ_filtre,valeur,doit_avoir_toute_les_valeurs,operateur_compare){
	this.champ_filtre = champ_filtre;
	this.valeur = valeur;
	this.doit_avoir_tout_les_valeurs = doit_avoir_toute_les_valeurs;
	this.operateur = operateur_compare;
	this.EstOK = function(camp){
		var donnee = camp.infos[this.champ_filtre];
		if(typeof(donnee) == "object"){
			return ifArrayInArrayShowMarker(this.valeur,donnee,this.doit_avoir_tout_les_valeurs);
		}
		else if(donnee){
			return eval("donnee "+this.operateur+" this.valeur  ");
		}
		return true;
	}
	function ifArrayInArrayShowMarker (array,array2,isOr){    
		if(typeof(isOr) == "undefined") isOr = false ;
		show = !isOr;
		if(array.length > 0){                       
			for(var j = 0;j<array.length && (!isOr ||(isOr && !show));j++){
							   
				if(!parseInt(array[j])){
					if(!isOr){
						if(!stringSearch(array[j],array2)){
						   show = false ;
						}
					}
					else{
						if(stringSearch(array[j],array2)){
						   show = true ;
						}
					}
				}
				else{
					if(!isOr){
						if(!dichotomicSearch(array[j],array2)){
							show = false ;
						}
					}
					else{
						if(dichotomicSearch(array[j],array2)){
						   show = true ;
						}
					}
				}
			}
			return show;
		}
	}
	function stringSearch(X,list){
		return list.indexOf(X) >= 0;
	}
	function dichotomicSearch(X,list){
		var middle , start,end,elt,debut;
		end = list.length;
		start = 0 ;
		while(start<=end){
			middle = Math.floor((start + end) / 2 );
			elt = list[middle];
			if(X == elt) return true ;
			if(parseInt(X) < parseInt(elt)){
				end = middle - 1 ;
			}
			else{
				start = middle + 1 ;
			}
		}
		return false ;
	}
}