﻿/*notes:

conversion coordonées GPS en points:
http://www.developpez.net/forums/d441910/autres-langages/algorithmes/transposer-coordonnees-gps-pixels-xy/

*/


// optimisation, mise en cache des $("elem") 
var e = []; //tableau contenant le cache des éléments

function ce(id) { 
    //Retourne l'objet (du cache, et s'il n'existe pas, va la chercher...)

    if ( !e[id] ) {
        e[id] = $(id);
    }

    return e[id];
}

var App = {
    //Application principale

    init: function() {
        Chrono.start("main");
        Debug.init();
        Status.init();
        Debug.log("Main init");
        Ticker.init();
        AppMeteo.init();
        //Hover.init();
        //Test.init();
        
        //Détection des iframes... pour savoir si on s'est fait encapsuler...
		
		
		if( top.location != self.location ) {
            //mettre IFRAME pour activer le style css qui limite le contenu à 450px
            $("#m-main").addClass("IFRAME");
            $("#m-main").addClass("IFRAME-height-" + ce(window).height() );
        } 
        
        
        
    }
    
};

var Ticker = {

    imgList: new Array(),
    run: true,
    delay: 6000, //ms
    timer: null,
    current: 0,

    init: function() {
        //Initialisation du ticker

        Debug.log("ticker init");
        
        var me = this;
        
        //recherche de la liste des images
		var imgs  = $("#ticker img");
		if (!imgs.length)
			return;
		
        imgs.each( function() {
            me.imgList.push($(this));
        });
 
        this.addControls();

        //on masque toutes les images (a la main pour éviter le premier fadeout)
        $("#ticker img").hide();
        
        //on affiche le premier ticker
        this.show();

        //on lance le timer...
        this.timer = setTimeout("Ticker.displayNext()", this.delay);
    },
    
    addControls: function() {
        //Ajout des boutons pour changer manuellement l'image, stopper et redémarrer le ticker
        
        var me = this;
        
        $("#ticker").append('<ul class="controls"></ul>');
        $(this.imgList).each( function() {
            $("#ticker .controls").append( '<li id="ticker-control-' + $(this).attr("data-id") + '"><a data-show="' + $(this).attr("data-id") + '" href="#">' + $(this).attr("alt") + '</a></li>' );     
        });
        
        //on ajoute les fonctions aux boutons
        $("#ticker .controls li a").click( function() {
            //on stoppe le défilement automatique
            me.stop();
            //force l'image courante.
            me.current = parseInt( $(this).attr("data-show") ) ;
            me.show();
            return false
        }); 
        
        //au clic sur le ticker, on force l'affichage de l'image suivante, et on redémare...
        $("#ticker").click( function() {
            me.run = true;
            me.displayNext();
        });
        
    },
    
    displayNext: function() {
        //Affiche l'image suivante
        
        clearTimeout( this.timer );
        
        //seulement si le défilement est en marche
        if( this.run ) {
            this.current += 1;
            
            //reset pour ne pas dépasser les bornes
            if( this.current >= this.imgList.length ) {
                this.current = 0;
            }
            
            this.show();
  
            //on relance le timer pour boucler...         
            this.timer = setTimeout("Ticker.displayNext()", this.delay);
        }
    
    },
    
    stop: function() {
        //Arrêt du défilement automatique des images
        
        clearTimeout( this.timer );
        this.run = false;
    },
    
    show: function() {
        //affiche l'image courante
        
        this.hideAll();
        //Affiche l'image elle-même
        this.imgList[this.current].fadeIn('slow');
        //met la classe active au bouton correspondant
        $("#ticker-control-" +  this.current ).addClass("active");
    },
    
    hideAll: function() {
        //masque toutes les images
            
        $("#ticker img").fadeOut('fast');
        $("#ticker li").removeClass("active");
    }
    
};

var AppMeteo = {
    //Application Météo

    running: false, //Est-ce que les images sont en train de défiller?
    delay: 100, //délais entre deux affichages [ms]
    timer1: null,
    timer2: null,
    loop: true, //est-ce qu'on tourne en boucle quand on arrive à la fin?
    startAfterLoading: false,
    type: null, //Quel type de page avons-nous ? player, switcher, video, ...
    hq: false, //Mode haute qualité??
    useGif: false, //Faut-il utiliser des gif à la place des png??

    init: function() {

        Status.start("AppMeteoInit");
        
       	if ($.browser.msie && $.browser.version == 6){
			// apply pngfix
			Debug.log("Browser is IE6...");
			this.useGif = true;
		}
		
		//Debug.log("Use Gifs? : " + AppMeteo.useGif);
		     
        //on met les classes sur le menu principal
        Controls.initMainMenu();
    
        //on vérifie à quel type de page à a affaire:
        //player,
        
        //this.type = $("body").attr("data-type");
        if( $("#m-cartes").length == 1 ) {
            this.type = "switcher";
        } 
        
        if( $("#mainImg").length == 1 ) {
            this.type = "animate";
        }
        
        if( $("#m-content #player").length == 1 ) {
            this.type = "video";
        }
 
        if( $("#m-lexique").length == 1) {
            this.type = "lexique";    
        }
 
 
        
        //DETECTER LES MAP
        
        
        Debug.log("type: " + this.type );
 
        switch( this.type ) {
            
            case "animate" :
                MainImage.init();
                Status.start("cacheInit");
                Controls.init();
                ProgressBar.init();
                Cache.init();
                break;
                
            case "switcher" :
                Switcher.init();
                break;
                
            case "video" :       
                Video.init();                
                break;
                
            case "lexique" :
                Lexique.init();
                break;
        }
 
        //DETECTION D'UN HOVER SUR CARTE NORMALES
        if( $("#m-cartes-hover").length == 1 ) {
            Status.start("hoverInit");
            Hover.init();
            Hover.loadXmlData();
        }

        //DETECTION DE LA CARTE TEMPERATURES OBSERVEES
        if( $("#m-obs-temp").length == 1 ) {
            Status.start("hoverTempInit");
            HoverTemp.init();
            HoverTemp.loadXmlData();
            //Hover.loadXmlData();
        }        
        
        //DETECTION DE LA CARTE VENTS OBSERVEES
        if( $("#m-obs-vents").length == 1 ) {
            Status.start("hoverVentsInit");
            HoverVents.init();
            HoverVents.loadXmlData();
        }         

        Alertes.init();

        Status.end("AppMeteoInit");
    },
    
    imgsListLoaded: function() {
        //est appellé par Cache pour signaler que la liste des images est chargée
        Debug.log("Images List Loaded count: " + Cache.count);
		Status.end("cacheInit");
		
		//on peut charger le slider (si on a des images!)
		
		if( Cache.count > 0 ) {
			Controls.initSlider();
			
			//on charge la première image
			if( Cache.loadLast != "1") {
				this.displayImage( 0 );
			} else {
				//on charge la dernière image...
				this.displayImage( Cache.count );
			}
		} else {
			//Il faut alerter l'utilisateur et lui dire qu'on a pas de données...
			MainImage.alert("Aucune image n'est actuellement disponible.");
		}		
    },
    
    AllImagesLoaded: function( q ) {
        Debug.log("All Images Loaded " + q);

        //la on a plus besoin de la progressbar3 ... on la balance
        ProgressBar.remove("3");
        
        //Si c'est après un clic sur play que l'image
		if( this.startAfterLoading ) {
		    this.startAfterLoading = false;
		    this.play();
		}

    },
    
    btnClicked: function( btn ) {
        Debug.log("btn " + btn + " CLICKED");
        
        switch( btn ) {
        
            case "btn-hq-switcher" :
            
                if( !Controls.isHq() ) {
                    Debug.log("Setting hq mode");
                    this.stop();
                    Controls.setHq();
                    this.hq = true;
                    this.prePlay();
                } else {
                    Debug.log("already in hq mode");
                }
                break;

            case "btn-first" :
                this.stop();
                this.displayImage( 0 );
                break;

            case "btn-last" :
                this.stop();
                this.displayImage( Cache.count -1 );
                break;

            case "btn-prev" :
                this.stop();
                this.displayImage( Cache.current -1 );
                break;

            case "btn-next" :
                this.stop();
                this.displayImage( Cache.current +1 );
                break;
                
            case "btn-play-stop" :
            
                //on va chercher le status (play ou stop)
                if ( Controls.isPlay() ) {
                    //on a cliqué sur play
                    this.prePlay();
                } else {
                    //on a cliqué sur stop
                    this.stop();
                }
                
                break;    
        }
    },
    
    prePlay: function() {
        //on vérifie si le cache est chargé
        
        Controls.displayStop();
        
        //on arrête le défilement du ticker...
        Ticker.stop();
        
        if( Cache.hqLoaded || ( Cache.lqLoaded && !this.hq )  ) {
            this.play();    
        } else {
            Debug.log("loading cache...");
            this.startAfterLoading = true;
            //on remet la barre à 0
            ProgressBar.reset("3");
            ProgressBar.activate("3");
            if( this.hq ) {
                Cache.loadAll('hq');
            } else {
                Cache.loadAll('lq');
            } 
        }
        
        
    },
    
    play: function() {
        //Debug.log("play");

        //Status.start("play");

        Controls.displayStop();
        
        
        this.displayImage( Cache.current + 1);

        //et on s'auto relance...
        //Attention aux limites...
        
        if( this.loop && (Cache.current >= ( Cache.count - 1)) ) {
            Cache.current = 0;   
        }
        
        if( Cache.current < ( Cache.count - 1)  ){        
            clearTimeout( this.timer1 );
            var code = "AppMeteo.play()";
            this.timer1 = setTimeout(  code , this.delay ) ;
        } else {
            Debug.log("limit -> stop");
            this.stop();
        }
        
    },
    
    stop: function() {
        //Debug.log("stop");
        clearTimeout( this.timer1 );
        Controls.displayPlay();
        //Status.end("play");
    },
    
    displayImage: function( key ) {
        //Debug.log("displayImage " + key);
        Cache.display( key );
    },
    
    getLast: function() {
        Debug.log("getLast");
        return ( Cache.count -1 ) ;
    },
    
    sliderMoved: function( val ) {
        //Debug.log("slider Moved " + val);
        this.stop();
        
        //si le cache est chargé, on lance imédiatement
        if( Cache.lqLoaded || Cache.hqLoaded ) {
            this.displayImage( val );    
        } else { //Sinon on attend un petit peu que le slider soit stabilisé... histoire de pas charger 50 images inutiles
            //Debug.log("!!!");
            clearTimeout( this.timer2 );
            var code = "AppMeteo.displayImage(" + val + ")";
            this.timer2 = setTimeout(  code , 100 ) ;
        }
        
        
    },
    
    imgDisplayed: function( key ) {
        //A réactiver pour afficher l'image actuelle dans la zone info
        //Info.display( Cache.getInfos( key ) );
        Controls.setSlider( key );
    },

/* Fonctions pour la partie Hover */
    hXmlLoaded: function() {
        Hover.parseXml();  
    },
    
    hDataReady: function() {
        //les xml ont été parsés, les données sont dans Hover.data
        Hover.addAllZones();
    },
    
    hAllZonesLoaded: function() {
        //toutes les zones sont chargée...
        //on commence par les cacher
        Hover.hideAllZones();

        //maintenant il faut initialiser l'imageMap qui est devant
        Hover.initImageMap();
        
        //et la on est prêt...
        Status.end("hoverInit");
        Debug.log("hover ready");
    },
    
/* Fonctions pour la partie Hover Temp */
    htXmlLoaded: function() {
        Debug.log("Hover Temp XML data loaded");
        HoverTemp.parseXml();
    },
    
    hoverTempReady: function() {
        Debug.log("Hover Temp Ready");
        HoverTemp.hideAllZones();
        //HoverTemp.showZone(14329);
    },
    
/* Fonctions pour la partie Hover Vents */
    hvXmlLoaded: function() {
        Debug.log("Hover Vents XML data loaded");
        HoverVents.parseXml();
    },
    
    hoverVentsReady: function() {
        Debug.log("Hover Vents Ready");
        HoverVents.hideAllZones();
        //HoverTemp.showZone(14329);
    }    
    
    
};

var Alertes = {

    init: function() {
        //on fait en sorte qu'au hover sur la carte, le menu passe aussi en hover
        ce("#m-alertes a").hover(function() {
            ce("#m-alertes a").addClass("hover");
        },function() {
            ce("#m-alertes a").removeClass("hover");
        });
        
    }
};

var Lexique = {
    init: function() {
        Debug.log("Init lexique");
        
        var me = this;
        
        ce("#m-lexique dl dt").click(function() {
            Debug.log("toggle");
            $(this).next().toggle("fast");
            $(this).toggleClass("active");
            return false;
        }).next().hide();
        
        $("#m-lex-showAll a").click( function() {
            me.showAll();
            return false;
        });
        
        $("#m-lex-hideAll a").click( function() {
            me.hideAll();
            return false;
        });

    },
    
    showAll: function() {
        Debug.log("show All");
        ce("#m-lexique dl dt").addClass("active").next().show();
    },
    
    hideAll: function() {
        ce("#m-lexique dl dt").removeClass("active").next().hide();
    }
};

var Video = {

    timer: null,
    delay: 3000, //ms, la fenêtre info se ferme après delay ms

    init: function() {
        Debug.log("Video.init");        
        this.getUrl();
    },
    
    getUrl: function() {
        Debug.log("loading video data");
        me = this;
        $.ajax({
            type: "GET",
            cache: false,
            async: false,
            //url: "getLastVideo.php",
            url: "getLastVideoV2.php",
            dataType: "text",
            success: function( data ) {
                Debug.log("URL LOADED...."); 
                //la il faut mémoriser les données...
				/*
                var s = document.createElement('script');
               
                s.src = data;
                s.setAttribute('async', 'true'); // html5 async
                document.documentElement.firstChild.appendChild(s);
                */
                var vid = data.match(/&vid=([0-9]+)/);
                if( vid.length == 2 ) vid = vid[1];
                else {
                	Debug.log("BAD VIDEO ID "+data); 
                	return false;
                }
                if( vid > 1 ){
		            $('#player').html('<object type="application/x-shockwave-flash" data="http://www.tsr.ch/v/player" style="width: 800px; height: 450px;"><param name="movie" value="http://www.tsr.ch/v/player"><param name="allowFullScreen" value="true"><param name="allowScriptAccess" value="always"><param name="FlashVars" value="id='+ vid +'"><a href="http://www.tsr.ch/video/#id='+ vid +'">Dernière émission météo</a></object>');
                }
                
            }
        });
        
    }/*,
    load: function(s) {
        
        Debug.log("Loading video");
        TSR.player.streamComplete = function(target) {
            //alert('stream complete for player with id: ' + target);
        };
        TSR.player.init('player');
        s.preview_image_url = Tools.getBasePath() + '/images/videoBG.jpg';
        TSR.player.addStream(s);
        
        var p = TSR.player.current;
        p.options.bigPlayColor = 0xffffff;
        p.options.bigPlayAlpha = .8;
        p.options.width = 800;
        p.options.height = 450;

        p.inject(s.xobix_video_id);   
        Debug.log(s.title + " " + s.broadcast_date);
		
        this.displayInfos( s.title + ": " + this.convertBroadcastDate( s.broadcast_date ) );
    },
    
    displayInfos: function( msg ) {
        ce("#m-emissionInfos").html( msg );
        //on masque après quelques secondes
        clearTimeout( this.timer );
        var code = "Video.hideInfos()";
        this.timer = setTimeout(  code , this.delay ) ;
    },
    
    convertBroadcastDate: function( bdate ) {
        //traduit broadcast date en un truc lisible
//        return bdate;
        return bdate.substr(8, 2) + "-" + bdate.substr(5, 2) + "-" + bdate.substr(0, 4);
    },
    
    hideInfos: function() {
        ce("#m-emissionInfos").hide();    
    }
    */
};

var Switcher = {

    current: null, //mémorisation de l'id actuel (pour éviter de réafficher...)

    init: function() {
       
        //on affiche la première image;
        this.show("show1");        
        var me = this;
        
        //assignation des fonctions aux boutons
        ce("#switcher-menu li").click( function() {
            me.show( $(this).attr('id') );
            return false;
        });
        
    },
    
    hideAll: function() {
        ce("#m-cartes > img").hide();
        //pour le hover
        ce("#m-cartes-hover .show").hide();
        //ce("#switcher-menu li").removeClass("active");
    },
    
    show: function(id) {
    
        if( this.current != id ) {
            this.current = id;
            //Debug.log("show image: " + id );
            this.hideAll();
            ce("#switcher-menu li").removeClass("active");
            $("#switcher-menu #" + id).addClass("active");
            ce("#switcher-" + id ).fadeIn();
            ce("#m-cartes-hover ." + id ).fadeIn();
        }
        
    }
};

var HoverTemp = {

    count: 0,
    xmlData: null,
    yMin: 45.73, //Latitude du bas de la carte
    yMax: 47.9, //latitude du haut de la carte
    xMin: 5.45, //longitude de la gauche de la carte
    xMax: 11.05, //longitude de la droite de la carte
    mapHeight: 450,
    mapWidth: 800,
    maxRight: 400, //position à partir de laquelle on affiche le popup à gauche du point
    maxBottom: 225, //Position à partir de laquelle on affiche le popup en dessous du point
    pointR: 6, //rayon du point (pour correction de la position)
    cTop: -15, //Correction de la position du hover
    cBottom: -13,
    cLeft: -3,
    cRight: -25,
    
    timeZoneOffset: null,

    init: function() {
        Debug.log("Hover Temp Init");
        
        this.timeZoneOffset = ce("#m-obs-temp img").attr('data-offset');
        Debug.log("Time Zone Offset " + this.timeZoneOffset);
        
    },
    
    loadXmlData: function() {
        Debug.log("load xml");
        $.ajax({
            type: "GET",
            cache: false,
            url: ce("#m-obs-temp img").attr('data-xmlFile'),
            dataType: "xml",
            success: function( xml ) {
                HoverTemp.xmlData = xml;
                AppMeteo.htXmlLoaded();
                
            }
        });
    },
    
    parseXml: function() {
        Debug.log("Parsing XML");
        //on traverse... et on tente de trouver le coordonées...
        var me = this;
        Chrono.start("Parsing XML");
        $(this.xmlData).find('record').each( function() {
            
            Debug.log( $(this).attr("station") + " lon:" + $(this).attr("lon") + " lat:" + $(this).attr("lat") + " x:" + me.cLon($(this).attr("lon")) + " y:" + me.cLat($(this).attr("lat")) );
            
            var alt = $(this).attr("altitude");
            
            
            var t = $(this).find('tre200bn').attr("time");            
            var hh = t.substr(8,2);
            //hh = "24";
            var mm = t.substr(10,2);

            
            
            
            var time = me.utc2local( hh, mm, t, 0 ) ;
            //var time = "00h00";
            
            var timeMoins1H = me.utc2local( hh, mm, t, -1 ) ;
            
            //Debug.log( time );
            
            var tempMin = $(this).find('tre200bn').text();
            //Debug.log(temp);
            var tempMax = $(this).find('tre200bx').text();
            
            //si on a des 999 (ou des -999), on a pas la température...
            if( Math.abs(tempMin) == 999 ) {
                tempMin = "--";
            }
            if( Math.abs(tempMax) == 999 ) {
                tempMax = "--";
            }
            
            var content = '<p class="top"><strong>' + $(this).attr("station") + '</strong></p><p class="bottom">Altitude: <strong>' + alt + 'm</strong><br>T min: <strong>' + tempMin + '°C</strong><br>T max: <strong>' + tempMax + '°C</strong><br><small>Mesures:<br> de ' + timeMoins1H + ' à ' + time + '</small></p>';
            
            //var content = '<p class="top"><strong>' + $(this).attr("station") + '</strong></p><p class="bottom">Altitude: <strong>' + alt + 'm</strong><br>T min: <strong>' + tempMin + '°C</strong><br>T max: <strong>' + tempMax + '°C</strong><br>Vitesse du vent: 25 m/s<br>Rafales : 150 m/s<br>Couche de neige: 15cm<br>Pression: 952.1 hPa<br><small>(mesures à ' + time + ')</small></p>';
            
            me.addDot( me.cLon($(this).attr("lon")), me.cLat($(this).attr("lat")), $(this).attr("id"), content  );
        });
        Chrono.sr("Parsing XML");
               
        //ajout de la fonction au hover sur le point
        ce("#m-obs-temp .dots1 .dot" ).hover(function() {
            //Debug.log("hover" + $(this).attr("data-id") );
            me.showZone( $(this).attr("data-id") );
            $(this).addClass("active");
        }, function(obj) {
            //$(obj).hide();
            me.hideAllZones();    
        });
        
        //fermeture des hover à la sortie de la carte
        ce("#m-obs-temp .dots1").hover(function() {}, function() {
            me.hideAllZones();
        });

        
        
        AppMeteo.hoverTempReady();
    },
    
    utc2local: function( hh, mm, timeStamp, hOffset ) {
        
        //Debug.log("timeStamp : " + timeStamp);
        
        //il faut ajouter this.timeZoneOffset heures à l'heure obtenue
        
        hh = parseInt( hh,10 );
        
        //il faut ajouter hOffset
        hh = hh + parseInt(hOffset);
                     
        var tzOffset = parseInt(this.timeZoneOffset);
        
        hhLocal = hh + tzOffset;
        
        //si on obtient 25, on met 1, si on obtient 24, on met 0
        //if( hhLocal == 25 ){ hhLocal = 1; }
        //if( hhLocal == 24 ){ hhLocal = 0; }
        
        //si on obtient plus que 23, on soustrait 24
        if( hhLocal > 23 ){ hhLocal -= 24; };
        
        //si on obtient moins que 0, on ajoute 24
        if( hhLocal < 0 ){ hhLocal += 24; }
        
         
        var out = hhLocal + "h" + mm;
        
        //Debug.log("timeStamp:" + timeStamp + " hh:" + hh + " tzOffset:" + tzOffset + " hhLocal:" + hhLocal + " mm:" + mm + " out : " + out );
        
        return out;
    },
    
    cLat: function( lat ) { //convertit la latitude en y (très approximatif...)
        return (Math.round( (lat-this.yMin) / (this.yMax-this.yMin) * this.mapHeight )) ;        
    },
    
    cLon: function( lon ) { //convertit la longitude en x (très approximatif...)
        return (Math.round( (lon-this.xMin) / (this.xMax-this.xMin) * this.mapWidth )) ;        
    },
    
    addDot: function( x, y, id, content ) {
    
        x = x - this.pointR;
        y = y - this.pointR;
    
        //ajout du point sur la carte de fond
        var html = '<div id="m-dot-' + id + '" data-id="' + id + '" class="dot" style="bottom:' + y + 'px;left:' + x + 'px;"></div>';
        ce("#m-obs-temp .dots1").append( html );
        
        //ajout de la zone de hover
        html = '<div id="m-z-h-' + id + '" data-id=' + id + ' class="m-data';
        if( x < this.maxRight ) {
            x = x + this.cLeft ;
            if( y < this.maxBottom) {    
                y = y + this.cBottom ;
                html += ' bottomLeft" style="bottom:' + y + 'px;left:' + x + 'px;"';
            } else {
                //on affiche en dessous du point
                y = this.mapHeight - y + this.cTop ;
                html += ' topLeft" style="top:' + y + 'px;left:' + x + 'px;"';
            }
        } else {
            //on affiche à gauche
            x = this.mapWidth - x + this.cRight;
            if( y < this.maxBottom) {
                y = y + this.cBottom ;
                html += ' bottomRight" style="bottom:' + y + 'px;right:' + x + 'px;"';
            } else {
                //on affiche en dessous du point
                y = this.mapHeight - y + this.cTop ;
                html += ' bottomRight" style="top:' + y + 'px;right:' + x + 'px;"';
            }
        }
        html += '>' + content + '</div>';
        ce("#m-obs-temp .data").append( html );
        
    },
       
    
    hideAllZones: function() {
        //Debug.log("hideAll");
        ce(".dots1 .dot").removeClass("active");
        ce("#m-obs-temp .m-data").hide();    
    },
    
    showZone: function( id ) {
        this.hideAllZones();
        ce("#m-z-h-" + id ).show();
    }

};

var HoverVents = {

    count: 0,
    xmlData: null,
    yMin: 45.73, //Latitude du bas de la carte
    yMax: 47.9, //latitude du haut de la carte
    xMin: 5.45, //longitude de la gauche de la carte
    xMax: 11.05, //longitude de la droite de la carte
    mapHeight: 450,
    mapWidth: 800,
    maxRight: 400, //position à partir de laquelle on affiche le popup à gauche du point
    maxBottom: 225, //Position à partir de laquelle on affiche le popup en dessous du point
    pointR: 6, //rayon du point (pour correction de la position)
    cTop: -15, //Correction de la position du hover
    cBottom: -13,
    cLeft: -3,
    cRight: -25,
    
    timeZoneOffset: null,

    init: function() {
        Debug.log("Hover Temp Init");
        
        this.timeZoneOffset = ce("#m-obs-vents img").attr('data-offset');
        Debug.log("Time Zone Offset " + this.timeZoneOffset);
        
    },
    
    loadXmlData: function() {
        Debug.log("load xml VENTS");
        $.ajax({
            type: "GET",
            cache: false,
            url: ce("#m-obs-vents img").attr('data-xmlFile'),
            dataType: "xml",
            success: function( xml ) {
                HoverVents.xmlData = xml;
                AppMeteo.hvXmlLoaded();
                
            }
        });
    },
    
    parseXml: function() {
        Debug.log("Parsing XML");
        //on traverse... et on tente de trouver le coordonées...
        var me = this;
        Chrono.start("Parsing XML");
        $(this.xmlData).find('record').each( function() {
            
            Debug.log( $(this).attr("station") + " lon:" + $(this).attr("lon") + " lat:" + $(this).attr("lat") + " x:" + me.cLon($(this).attr("lon")) + " y:" + me.cLat($(this).attr("lat")) );
            
            var alt = $(this).attr("altitude");
            
            
            var t = $(this).find('tre200bn').attr("time");            
            var hh = t.substr(8,2);
            //hh = "24";
            var mm = t.substr(10,2);

            
            
            
            var time = me.utc2local( hh, mm, t, 0 ) ;
            //var time = "00h00";
            
            var timeMoins1H = me.utc2local( hh, mm, t, -1 ) ;
            
            //Debug.log( time );
            
            //METTRE ICI L'ADAPTATION POUR LES VENTS!
            var dir = $(this).find('dkl010b0').text();
            var force = $(this).find('fkl010b0').text();
  
            //si on ne recois pas de données, dir=0 et force=0 !
            //ATTENTION!! vérifier quelles sont les valeurs envoyées quand on ne les a pas...
            // Modif EG, le 25.08.2010

            if (( dir == 0 ) && ( force == 0 )) {
                dir = "--";
                force = "--";
            } else {
            	force = Math.round(force * 3.6, 0);
            }

//            if( Math.abs(dir) == 999 ) {
//                dir = "--";
//            }
//            
//            if( Math.abs(force) == 999 ) {
//                force = "--";
//            } else {  
//				//passage en km/h
//				force = Math.round(force * 3.6, 0); 
//            }
            
            //on traduit les angles en francais...
            var dirCard = "--";
            if( dir > 337) {
            	dirCard = "N";
            } else if ( dir > 292) {
            	dirCard = "NW";	
            } else if ( dir > 247) {
            	dirCard = "W";	
            } else if ( dir > 202) {
            	dirCard = "SW";	
            } else if ( dir > 157) {
            	dirCard = "S";	
            } else if ( dir > 112) {
            	dirCard = "SE";	
            } else if ( dir > 67) {
            	dirCard = "E";	
            } else if ( dir > 22) {
            	dirCard = "NE";	
            } else if ( dir > 0) {
            	dirCard = "N";	
            }
            
            
            
            /*
            var tempMin = $(this).find('tre200bn').text();
            //Debug.log(temp);
            var tempMax = $(this).find('tre200bx').text();
            
            //si on a des 999 (ou des -999), on a pas la température...
            if( Math.abs(tempMin) == 999 ) {
                tempMin = "--";
            }
            if( Math.abs(tempMax) == 999 ) {
                tempMax = "--";
            }
            */
            
            var content = '<p class="top"><strong>' + $(this).attr("station") + '</strong></p><p class="bottom"><img src="fleche.php?ang=' + dir + '" alt="">Altitude: <strong>' + alt + 'm</strong><br>Vitesse: <strong>' + force + ' km/h</strong><br>Direction: <strong>' + dir + '° (' + dirCard + ')</strong><br><small>Mesures:<br> de ' + timeMoins1H + ' à ' + time + '</small></p>';           
            
            
            //var content = '<p class="top"><strong>' + $(this).attr("station") + '</strong></p><p class="bottom">Altitude: <strong>' + alt + 'm</strong><br>T min: <strong>' + tempMin + '°C</strong><br>T max: <strong>' + tempMax + '°C</strong><br><small>Mesures:<br> de ' + timeMoins1H + ' à ' + time + '</small></p>';
            
            //var content = '<p class="top"><strong>' + $(this).attr("station") + '</strong></p><p class="bottom">Altitude: <strong>' + alt + 'm</strong><br>T min: <strong>' + tempMin + '°C</strong><br>T max: <strong>' + tempMax + '°C</strong><br>Vitesse du vent: 25 m/s<br>Rafales : 150 m/s<br>Couche de neige: 15cm<br>Pression: 952.1 hPa<br><small>(mesures à ' + time + ')</small></p>';
            
            me.addDot( me.cLon($(this).attr("lon")), me.cLat($(this).attr("lat")), $(this).attr("id"), content  );
        });
        Chrono.sr("Parsing XML");
               
        //ajout de la fonction au hover sur le point
        ce("#m-obs-vents .dots1 .dot" ).hover(function() {
            //Debug.log("hover" + $(this).attr("data-id") );
            me.showZone( $(this).attr("data-id") );
            $(this).addClass("active");
        }, function(obj) {
            //$(obj).hide();
            me.hideAllZones();    
        });
        
        //fermeture des hover à la sortie de la carte
        ce("#m-obs-vents .dots1").hover(function() {}, function() {
            me.hideAllZones();
        });

        
        
        AppMeteo.hoverVentsReady();
    },
    
    utc2local: function( hh, mm, timeStamp, hOffset ) {
        
        //Debug.log("timeStamp : " + timeStamp);
        
        //il faut ajouter this.timeZoneOffset heures à l'heure obtenue
        
        hh = parseInt( hh,10 );
        
        //il faut ajouter hOffset
        hh = hh + parseInt(hOffset);
                     
        var tzOffset = parseInt(this.timeZoneOffset);
        
        hhLocal = hh + tzOffset;
        
        //si on obtient 25, on met 1, si on obtient 24, on met 0
        //if( hhLocal == 25 ){ hhLocal = 1; }
        //if( hhLocal == 24 ){ hhLocal = 0; }
        
        //si on obtient plus que 23, on soustrait 24
        if( hhLocal > 23 ){ hhLocal -= 24; };
        
        //si on obtient moins que 0, on ajoute 24
        if( hhLocal < 0 ){ hhLocal += 24; }
        
         
        var out = hhLocal + "h" + mm;
        
        //Debug.log("timeStamp:" + timeStamp + " hh:" + hh + " tzOffset:" + tzOffset + " hhLocal:" + hhLocal + " mm:" + mm + " out : " + out );
        
        return out;
    },
    
    cLat: function( lat ) { //convertit la latitude en y (très approximatif...)
        return (Math.round( (lat-this.yMin) / (this.yMax-this.yMin) * this.mapHeight )) ;        
    },
    
    cLon: function( lon ) { //convertit la longitude en x (très approximatif...)
        return (Math.round( (lon-this.xMin) / (this.xMax-this.xMin) * this.mapWidth )) ;        
    },
    
    addDot: function( x, y, id, content ) {
    
        
        x = x - this.pointR;
        y = y - this.pointR;
    
        //ajout du point sur la carte de fond
        var html = '<div id="m-dot-' + id + '" data-id="' + id + '" class="dot" style="bottom:' + y + 'px;left:' + x + 'px;"></div>';
        ce("#m-obs-vents .dots1").append( html );
        
        //ajout de la zone de hover
        html = '<div id="m-z-h-' + id + '" data-id=' + id + ' class="m-data';
        if( x < this.maxRight ) {
            x = x + this.cLeft ;
            if( y < this.maxBottom) {    
                y = y + this.cBottom ;
                html += ' bottomLeft" style="bottom:' + y + 'px;left:' + x + 'px;"';
            } else {
                //on affiche en dessous du point
                y = this.mapHeight - y + this.cTop ;
                html += ' topLeft" style="top:' + y + 'px;left:' + x + 'px;"';
            }
        } else {
            //on affiche à gauche
            x = this.mapWidth - x + this.cRight;
            if( y < this.maxBottom) {
                y = y + this.cBottom ;
                html += ' bottomRight" style="bottom:' + y + 'px;right:' + x + 'px;"';
            } else {
                //on affiche en dessous du point
                y = this.mapHeight - y + this.cTop ;
                html += ' bottomRight" style="top:' + y + 'px;right:' + x + 'px;"';
            }
        }
        html += '>' + content + '</div>';
        ce("#m-obs-vents .data").append( html );
        
    },
       
    
    hideAllZones: function() {
        //Debug.log("hideAll");
        ce(".dots1 .dot").removeClass("active");
        ce("#m-obs-vents .m-data").hide();    
    },
    
    showZone: function( id ) {
        this.hideAllZones();
        ce("#m-z-h-" + id ).show();
    }

};

var Hover = {
    
    xmlData: null,
    xmlPositions: null,
    data: new Array(),
    jLayer1: null, //Quelle partie des données faut-il mettre ? J0 J1?
    jLayer2: null,
    aprMat1: null,
    aprMat2: null,

    init: function() {
    
        Debug.log("Hover test");
        
        //on cherche quelle partie des données il faut afficher
        this.jLayer1 = ce("#m-cartes-hover .show1").attr("data-j");
        this.jLayer2 = ce("#m-cartes-hover .show2").attr("data-j");
        this.aprMat1 = ce("#switcher-show1").attr("data-aprMat");
        this.aprMat2 = ce("#switcher-show2").attr("data-aprMat"); 
        
        Debug.log("Layer1:" + this.jLayer1 + " Layer2:" + this.jLayer2);
        
    },
    
    loadXmlData: function() {
        Debug.log("load xml");
        $.ajax({
            type: "GET",
            cache: false,
            url: "meteodata/CH_MAPS/Rollovers.xml",
            dataType: "xml",
            success: function( xml ) {
                Hover.xmlData = xml;
                //Exceptionellement, on ne passe pas par le contrôleur...
                Hover.loadXmlPositions();
            }
        });
    },
    
    loadXmlPositions: function() {
        Debug.log("XML DATA LOADED");
        $.ajax({
            type: "GET",
            cache: true,
            url: "data/stationsPositions.xml",
            dataType: "xml",
            success: function( xml ) {
                Hover.xmlPositions = xml;    
                AppMeteo.hXmlLoaded();
            }
        });    
    },
    
    parseXml: function() {
        Debug.log("Parsing Xmls");

        var j = new Array();
        j[0] = "J0";
        j[1] = "J1";
        
        var me = this;
        //on traverse le xml des positions
        $(this.xmlPositions).find("ZONE").each( function() {
            var id = $(this).attr("id");
            
            me.data[id] = new Array();
            me.data[id]['nom'] = $(this).find("NOM").text();

            me.data[id]['x'] = $(this).find("x").text();
            me.data[id]['y'] = $(this).find("y").text();
            
        });
        
        //on traverse ensuite le xml des données
        $(this.xmlData).find("ZONE").each( function() {        
            var id = $(this).attr("id");
            me.data[id]['J0'] = new Array();
            me.data[id]['J1'] = new Array();
            
            for ( x in j ) {
 
                $(this).find(j[x]).each( function() { //each? y'en a qu'un...
                    me.data[id][j[x]]['SYMMAT'] = $(this).find("SYMMAT").text();
                    me.data[id][j[x]]['SYMAPR'] = $(this).find("SYMAPR").text();
                    
                    if( $(this).find("TEMPERATURES").attr("type") == 'minmax' ) {
                        me.data[id][j[x]]['MIN'] = $(this).find("MIN").text();
                        me.data[id][j[x]]['MAX'] = $(this).find("MAX").text();
                    } 
                    
                    if( $(this).find("TEMPERATURES").attr("type") == 'altitude' ) {
                        me.data[id][j[x]]['T2000'] = $(this).find("T2000").text();
                        me.data[id][j[x]]['T3000'] = $(this).find("T3000").text();
                    } 
                    
                });
            
            }
            
            //Debug.log("id:" + id + " nom:" + me.data[id]['nom'] + " x:" +  me.data[id]['x'] + " y:" +  me.data[id]['y'] + " minJ0:" + me.data[id]['J0']['MIN'] + " T2000J1:" + me.data[id]['J1']['T2000']);

        });
        
        //la on a toutes les données... 
        AppMeteo.hDataReady();
    },
    
    addAllZones: function() {
        Debug.log("Add All Zones");
        
        var me = this;
        
        for( id in this.data ) {
            
            //Debug.log(this.data[id]['nom']);    
            //on regarde si on a des coordonées (on se contente de vérifier si on a x)
            if( this.data[id]['x'] ) {
                //Debug.log("******Adding:" + this.data[id]['nom'] + " : " + id);              
                
                //PREMIERE COUCHE
                //le titre
                var html = '<p><strong>' + this.data[id]['nom'] + '</strong></p>';
                
                //l'illustration
                var sym = 'SYM' + me.aprMat1;
                //Debug.log(sym);
                //html += '<img src="' + this.data[id][me.jLayer1][sym] + '" alt="' + this.data[id][me.jLayer1][sym] + '">';
                //html += '<div class="m-hover-illustration">' + this.data[id][me.jLayer1][sym] + '</div>';
                
                
                //Températures
                if( this.data[id][this.jLayer1]['MAX'] ) {
                    html += '<p class="m-hover-temp">minimales : ' + this.data[id][this.jLayer1]['MIN'] + '°C<br>maximales : ' + this.data[id][this.jLayer1]['MAX'] + '°C</p>';
                }
                
                if( this.data[id][this.jLayer1]['T2000'] ) {
                    html += '<p class="m-hover-temp">à 2000 m : ' + this.data[id][this.jLayer1]['T2000'] + '°C<br>à 3000 m : ' + this.data[id][this.jLayer1]['T3000'] + '°C</p>';
                }

                me.addZone( this.data[id]['x'], this.data[id]['y'], id, 1, html, this.data[id][me.jLayer1][sym]);
                
                //SECONDE COUCHE
                //var html = '<p>Couche 2' + this.data[id]['nom']+ '</p>';
                //me.addZone( this.data[id]['x'], this.data[id]['y'], id, 2, html, "ABKN");

                //le titre
                var html = '<p><strong>' + this.data[id]['nom'] + '</strong></p>';
                
                //l'illustration
                var sym = 'SYM' + me.aprMat2;
                //Debug.log(sym);
                //html += '<img src="' + this.data[id][me.jLayer1][sym] + '" alt="' + this.data[id][me.jLayer1][sym] + '">';
                //html += '<div class="m-hover-illustration">' + this.data[id][me.jLayer1][sym] + '</div>';
                
                
                //Températures
                if( this.data[id][this.jLayer2]['MAX'] ) {
                    html += '<p class="m-hover-temp">minimales : ' + this.data[id][this.jLayer2]['MIN'] + '°C<br>maximales : ' + this.data[id][this.jLayer2]['MAX'] + '°C</p>';
                }
                
                if( this.data[id][this.jLayer2]['T2000'] ) {
                    html += '<p class="m-hover-temp">à 2000 m : ' + this.data[id][this.jLayer2]['T2000'] + '°C<br>à 3000 m : ' + this.data[id][this.jLayer2]['T3000'] + '°C</p>';
                }

                me.addZone( this.data[id]['x'], this.data[id]['y'], id, 2, html, this.data[id][me.jLayer2][sym]);



                
                
            }
            
        }
        
        //une fois qu'on a tout chargé, on masque toutes les zones
        
        
        //on a tout chargé, il faut changer les background pour avoir les bons symboles
 
        ce(".m-cartes-hover-zone").each( function() {
            //Debug.log( $(this).attr("data-bg") );
            if( AppMeteo.useGif ) { 
				$(this).children('p').css("background-image","url(../images/symboles/" + $(this).attr("data-bg") + ".gif)");
			} else {
				$(this).children('p').css("background-image","url(../images/symboles/" + $(this).attr("data-bg") + ".png)");
			}
            //$(this).children('p').css("background-color","red");

        });
        
        AppMeteo.hAllZonesLoaded();
 
    },
      
    addZone: function( x, y, id, layer, html, mclass ) {
        //Debug.log( "addZone x:" + x + " y:" + y + " layer:" +layer );
        
        //on transforme y pour qu'il soie le compte depuis le bas de la carte
        y = 450 - y;
        
        
        //ce("#m-cartes-hover .show" + layer).append('<div class="m-cartes-hover-zone" style="top:' + y + 'px;left:' + x + 'px;" id="m-cartes-hover-zone' + id + '-layer' + layer + '" ><div class="m-cartes-hover-content">' + html + '</div></div>');
        ce("#m-cartes-hover .show" + layer).append('<div data-bg="' + mclass + '" class="m-' + mclass + ' m-cartes-hover-zone m-cartes-hover-zone' + id + '" style="bottom:' + y + 'px;left:' + x + 'px;" id="m-cartes-hover-zone' + id + '-layer' + layer + '" >' + html + '</div>');

    },
    
    hideAllZones: function() {
        //Debug.log("hide all content");
        ce(".m-cartes-hover-zone").hide();
    },
    
    showZone: function( id ) {
        //Debug.log("showing: " + id);
        this.hideAllZones();
        ce( ".m-cartes-hover-zone" + id ).show();
    },
    
    initImageMap: function() {

        var me = this;

        //on active l'image-map
        $("#m-image-map img").show();
        
        //Détection des hover
        $('area.m-zone').hover(function() {
            //Debug.log("Map hover" + $(this).attr("data-zone")); 
            me.showZone( $(this).attr("data-zone") );
        }, function() {
            me.hideAllZones();
        });
        
        //Détection de la sortie de suisse
        //Détection des hover
        $('area.m-zone-suisse').hover(function() {
            //rien
        }, function() {
            me.hideAllZones();
        });
        
    }

};

var Info = {
    display: function( msg ) {
        ce(".info2 p").html( msg );
    }
};

var MainImage = {
    
    width: null,
    height: null,

	init: function() {
		//recherche de la largeur de l'image
		this.width = ce("#backgroundImg").attr('width');
		this.height = ce("#backgroundImg").attr('height');
        Debug.log("size : " + this.width + "x" + this.height);
	},
	
	alert: function(msg) {
		//Remplace l'image par un message d'alerte
		ce("#backgroundImg").replaceWith("<div class=\"alert\">" + msg + "</div>");
	}
    
};

var Cache = {

    pathHq: null, //Dossier des images haute qualité
    pathLq: null, //Dossier des images base qualité
    hqQ: null, //Qualité haute def
    lqQ: null, //Qualité basse def
    data: null, //
    data2: new Array(),
    count: null, //Nombre d'images
    listLoaded: false, //Est-ce que la liste d'images est chargée
    xmlFile: null, //fichier xml de déscription (avec la liste des images)
    
    loadLast: null, //charge la dernière image en premier
    
    

	hqToLoad: null,
	lqToLoad: null,
	
	hqLaunched: false,
	lqLaunched: false,
	hqLoaded: false,
	lqLoaded: false,
	
	timer1: null,
    current: 0,
    toHide: null, //Image à effacer avant d'afficher la suivante
    
    hqAfter: 250, //Chargement de la haute def après hqAfter [ms]

    init: function() {
        //Initialisation du cache image.
        Debug.log("CacheInit");
        
        this.pathHq = ce("#backgroundImg").attr('data-pathhq');
        this.pathLq = ce("#backgroundImg").attr('data-pathlq');
        this.lqQ = ce("#backgroundImg").attr('data-lqQ');
        this.hqQ = ce("#backgroundImg").attr('data-hqQ');
        this.loadLast = ce("#backgroundImg").attr('data-last');
        
        if( ce("#backgroundImg").attr('data-wait') ) {
            Debug.log( "wait OK -> :" + ce("#backgroundImg").attr('data-wait') );
            AppMeteo.delay = ce("#backgroundImg").attr('data-wait');
        } else {
            Debug.log( "wait:" + ce("#backgroundImg").attr('data-wait') );
        }
    
        
        Debug.log("hq: " + this.pathHq);
        Debug.log("lq: " + this.pathLq);
        
        this.loadList();
        
        //Debug.stop();
        
    },

    loadList: function() {
        //Recherche de la liste des images (ajax) sur le serveur
    
        var me = this;
        
        //on commence par mettre l'image de fond...
        ce("#preload").append('<div class="background"><img src="/images/sunshine-nb.gif" alt="" width="' + MainImage.width + '" height="' + MainImage.height + '"></div>');

        Chrono.start("loadingJSON");
        $.getJSON("getList2.php?path=" + this.pathLq , function(json) {
            Chrono.sr("loadingJSON");
            me.data = json;
            me.count = me.hqToLoad = me.lqToLoad = json.length;
            me.listLoaded = true;
            
            //On crée les images vide... on préchagera plus tard, mais il faut déjà les boites
            
            var code = "";
            $(json).each( function( key,val ) {
                
                me.data2[key] = new Array();
                me.data2[key]['val'] = val;
				me.data2[key]['lq'] = false;
				me.data2[key]['hq'] = false;
				                
                code += '<div class="preloadBox" id="preload-' + key + '" ><img data-key="' + key + '" data-q ="lq" class="lq" src="/images/trans.gif" alt="" width="' + MainImage.width + '" height="' + MainImage.height + '"><img data-key="' + key + '" data-q="hq" class="hq" src="/images/trans.gif" alt="" width="' + MainImage.width + '" height="' + MainImage.height + '"></div>'; 

            });
            
            ce("#preload").html(code);
            
            //on masque tout:
            ce("#preload .preloadBox").hide();
            
            //détection du chargement 
            
            ce("#preload img").load( function() {
                var key = $(this).attr("data-key");
                var q = $(this).attr("data-q");
                me.imgLoaded( key, q );
            });      
            
            //on signale à l'application que la liste est chargée
            AppMeteo.imgsListLoaded();
        });

    },
    
    imgLoaded: function( key , q ) {
		//Une image a été chargée...
		
		//ATTENTION!! FF DETECTE DEUX CHARGEMENTS DE L'IMAGE 0

		//Debug.log("loaded : " + q + " : " + key + " lq:" + this.lqToLoad + " hq:" + this.hqToLoad);

		Status.end("loading" + key + q);
		
		//Si c'est parceque le gif transparent est loadé, il faut ignorer...
		var ignore = "/images/trans.gif"; 
		var src = ce( "#preload-" + key + " ." + q ).attr("src");
		
		//on ne garde que la fin, parceque ie7 il met l'url complète...
		src = src.substring( src.length - ignore.length, src.length);
		//Debug.log( src );
		
		/*
		if( src == ignore ) {
		    //Debug.log("image is " + ignore + " -> abort");
		    return;
		} else {
		    //Debug.log( "loaded: " + src + " key:" + key + " q:" +q);
		}
		
		//on stoppe aussi tout si on a déjà marqué le load...
		if( this.data2[key][q] == true ) {
		    //Debug.log( "already tagged -> abort ");
		    return;
		} else {
		    this.data2[key][q] = true;
		}
		*/
		
		//On stoppe si l'image est a ignorer ou si on a déjà compté le load
		if( (src == ignore) || this.data2[key][q] ) {
		    return;
		} else {
		    this.data2[key][q] = true;
		}
		
		
		
		if( q == "lq" ) {
		
            this.lqToLoad --;
			//ProgressBar.set( this.count - this.lqToLoad, this.count, "1");
			ProgressBar.set( this.count - this.lqToLoad, this.count, "3");

			if( this.lqToLoad == 0){
				//Debug.log("All lq loaded");
				this.lqLoaded = true;
				Status.end("lqLoading");
				AppMeteo.AllImagesLoaded(q);

			}
		}
	
		if( q == "hq" ) {
		
			this.hqToLoad --;	
			//ProgressBar.set( this.count - this.hqToLoad, this.count, "2");
            ProgressBar.set( this.count - this.hqToLoad, this.count, "3", "Chargement HQ");

			if( !this.hqToLoad ){
				//Debug.log("All hq loaded");
				this.hqLoaded = true
				Status.end("hqLoading");
				AppMeteo.AllImagesLoaded(q);
			}			

		}
		
		

	},

	loadAll: function( q ) {
		//Charge toutes les images
		//q : hq ou lq

        Debug.log("****LOAD ALL****** " + q);

		var q = ( q == null ) ? "lq" : q; //Mise par défaut a low quality
		var block = true;
		
		//on vérifie d'abord si on le fait ou pas...
		if( ( q == "lq" ) && !this.lqLoaded && !this.lqLaunched  ) {
			this.lqLaunched = true;
			//this.lqToLoad = this.count;
			block = false;
			Status.start("lqLoading");
			Debug.log("Loading LQ images : " + this.lqToLoad);
		} 

		if( ( q == "hq" ) && !this.hqLoaded && !this.hqLaunched  ) {
			this.hqLaunched = true;
			//this.hqToLoad = this.count;
			block = false;
			Status.start("hqLoading");
			Debug.log("Loading HQ images");
		} 
		
		if( block ) {
			Debug.log("block");
			return;
		}

		Debug.log("Loading images : " + q);

	    var me = this;
        $(this.data).each( function( key ) {
            me.loadOne( key, q );
        });
	},
	
	loadOne: function( key, q ) {
	    //Charge une image...
        //on doit pouvoir optimiser ca... on fait pleins de fois var p... 
        //on doit aussi pouvoir chainer addclass et children...
        
        //on ne charge que se c'est pas déjà fait
        /*
        if( ce("#preload-" + key).hasClass(q) ) {
            //on laisse tomber...
            return;
        }
        */
        
        if( this.isLoaded( key, q ) ) {
            return;
        }
        
        if ( q == 'lq') {
            Status.start("loading" + key + q);    
        } else {
            Status.start("loading" + key + q, false);
        }
        
        //ce("#preload-" + key).addClass(q);
        
        var val = this.data[key];
        
        var q2 = ( q == "lq" ) ? this.lqQ : this.hqQ ; //Qualité de l'image
        
        var p = "img?w=" + MainImage.width + "&h=" + MainImage.height + "&q=" + q2 + "&img="; //début de l'url de l'image
        
        var f = ( q == "lq" ) ? this.pathLq : this.pathHq; //dossier contenant
        
        var src = p + f + val;
        
        //Debug.log( "**" + src );
        
        //ce("#preload-" + key + " ." + q).attr('src', p + "/" + val).removeClass("notLoaded");
        //ce("#preload-" + key + " ." + q).attr('src', f + "/" + val);
        
        ce("#preload-" + key + " ." + q).attr('src', src);
        
	},
	
	isLoaded: function( key , q ) {
	    //regarde si un id particulier est chargé (en qualité voulue)
	    
	    /*
	    if( ce("#preload-" + key).hasClass(q) ) {
	        return true;
	    } 
	    return false;
	    */
	    
	    //version avec data2
	    
	    if( this.data2[key][q] ) {
	        return true;
	    }
	    
	    return false;
	    
	    
	},
	
	display: function( key ) {
	    //affiche l'image key

        //Chrono.start("display");
        //Status.start("display");
	    //On commence par limiter...
	    if( key < 0 ) {
            Debug.log("low limit...");
	        key = 0;
	    }
	    
        if( key > (this.count -1) ) {
            Debug.log("hi limit...");
	        key = this.count -1 ;
	    }
	    
	    //Debug.log("Display " + key);
	    
	    /*
	    if( this.isLoaded( key, "hq" ) ) {
	        Debug.log("Loading hq...");
	    } else if( this.isLoaded( key, "lq" ) ) {
	        Debug.log("Loading lq...");
	    } else {
	        Debug.log("NOT LOADED... abort...");
	    }
	    */
	    
	    if( this.isLoaded( key, "lq" ) || this.isLoaded( key, "hq" ) ) {
            //rien
	    } else {
	        //NOT LOADED...
	        //on force son chargement (en lq pour l'instant)
	        Debug.log("not pre loaded... ");
	        this.loadOne( key, "lq");
	    }

        //on affiche le div qui contient les images...
        //Si la hq est chargée, elle apparaitra devant.
        
        //on peut faire mieux, ne cacher que le calque précédent qui est probablement le seul affiché
        //ce(".preloadBox").addClass("hidden");
        
        //ce("#preload-" + key ).removeClass("hidden");
        //ce("#preload-" + this.toHide ).addClass("hidden");
        ce("#preload-" + key ).show();
        ce("#preload-" + this.toHide ).hide();
        this.toHide = key;
        
        //ce(".preloadBox").hide();
        //ce("#preload-" + key ).fadeIn();
        //Debug.log("prev: " + this.current + " current: " + key);
        this.current = key;
        this.imgDisplayed( key );
        //Status.end("display");
        //Chrono.sr("display");
	       
	},
	
	imgDisplayed: function( key ) {
	    //lancé après l'affichage de l'image. ATTENTION!! pas après le load... on a juste affiché le div

	    //Debug.log("Image " + key + " displayed hd? " + hq);
	    
	    //on lance le chargement de la haute def après un petit moment...
	    
	    if( !this.isLoaded( key, "hq" ) ) {
	        //Debug.log("lancer la haute def...");
	        
	        clearTimeout( this.timer1 );
            var code = "Cache.loadOne( " + key + ", 'hq')";
            this.timer1 = setTimeout(  code , this.hqAfter ) ;
	        //this.loadOne( key, "hq" );
	    }
	    
	    //retour à l'application
	    AppMeteo.imgDisplayed( key );
	    
	},
	
	getInfos: function( key ) {
	    //Retourne les infos de l'image à afficher
	    //Debug.log( "Infos : " + key);
	    
	    var txt = this.data[key];
	    
	    return txt;
	}
	
};

var Controls = {

	s1: null, //le slider
	
	init: function() {
	
	    //this.initMainMenu();

		//on affiche le bouton play
		//ce("#play-stop").removeClass("hidden");
		
		//Comportement général des boutons au hover et au mousedown
        ce(".btn").hover(function(){
            $(this).addClass("hover");
        },function(){
            $(this).removeClass("hover");
        });
       
        /*           
        ce(".btn").mousedown(function() {
            $(this).addClass("down");
        });

        ce(".btn").mouseup(function() {
            $(this).removeClass("down");
        });
        */
        
        //Comportement des boutons au click
        ce(".btn").click( function() {
            //Debug.log( "click " + $(this).attr("id") );
            AppMeteo.btnClicked( $(this).attr("id") );
            return false;
        });
	},
	
	initSlider: function() {
	
	    Debug.log("initSlider");

        var me = this;
        this.s1 = ce("#sliderContainer .slider");        
        
        //Création du slider
        this.s1.slider({
            change: function( event, ui) {               
                //AppCam.slider1Changed();
            },
            slide: function( event, ui) {
                //on avertit l'application au moment du slide
                me.sliderChanged( ui.value );
            },
            min: 0,
            max: AppMeteo.getLast(),
            animate: true //positionne le slider en douceur quand on clique sur la barre
        });
    
    },
    
    sliderChanged: function( val ) {
        //Debug.log( "Slider moved to : " + val );
        AppMeteo.sliderMoved( val );
    },
	
    setSlider: function( val ) {
        //Repositionne le slider.
    
        //Debug.log("Setting slider value : " + val );
        this.s1.slider('option', 'value', val);
    }, 
	
	
	isPlay: function() {
	    
	    if( ce("#btn-play-stop").hasClass("play") ) {
	        return true;
	    } 
	    
	    return false;
	},
	
	displayPlay: function() {
	    //Debug.log("displayPlay");
	    //ce("#btn-play-stop span").html("play");
	    ce("#btn-play-stop").removeClass("stop").addClass("play");
	},
	
	displayStop: function() {
        //Debug.log("displayStop");
        
	    ce("#btn-play-stop").removeClass("play").addClass("stop");
	    //marche pas... ca supprime la fonction du bouton??
	    //ce("#btn-play-stop span").html("stop");
	},
	
	setHq: function() {
	    ce("#btn-hq-switcher").addClass("hq");    
	},
	
	isHq: function() {
	
	    if( ce("#btn-hq-switcher").hasClass("hq") ) {
	        return true;
	    } 
	    
	    return false;	    
	},
	
	initMainMenu: function() {
        //ajoute les bonne classes au menu principal
        Debug.log("-----Menu-----");
        var m1 = ce("#m-main").attr("data-m1");
        var m2 = ce("#m-main").attr("data-m2");
        var me = this;
        Debug.log( m1 + " - " + m2);
        
        ce("#m-menu ." + m2 ).addClass("active");
        ce("#m-menu ." + m1 ).addClass("active");
        
        //on va tenter un truc pour IE6....
        if( m2 == 'unused' ) {
        	ce("#m-menu ." + m1 ).addClass("displayed");	
        } else {
			ce("#m-menu ." + m2 ).addClass("displayed");	
        }
        //on enlève la class displayed à tous les éléments qui ont une class down
        ce("#m-menu li").each( function() {
        	if(	$(this).hasClass("down") ) {
        		$(this).removeClass("displayed");
        	}
        });
        
        //Si on a en même temps la class down et active, on met downActive... (INUTILE)
        /*
        if( ce("#m-menu ." + m1 ).hasClass('down') && ce("#m-menu ." + m1 ).hasClass('active') ) {
        	ce("#m-menu ." + m1 ).addClass('downActive');	
        }
		if( ce("#m-menu ." + m2 ).hasClass('down') && ce("#m-menu ." + m2 ).hasClass('active') ) {
        	ce("#m-menu ." + m2 ).addClass('downActive');	
        }
        */
        
        
        
        Debug.log("#m-menu ." + m2);
        
        //On initialise les title...
        //Boucle à travers tous les title qu'on trouve sur les a du menu
        var titles = $('.level1menu [title]') ;
	    Debug.log("nb title : " + titles.length );
	    Debug.log( titles );
	    
	    for( var i = 0 ; i < titles.length ; i++ ) {
	        
	        //si le title est vide, on laisse tomber
	        if( $(titles[i]).attr('title') == "" ) {
	            Debug.log("title " + i + " is empty");
	        } else {
                Debug.log("title " + i + ": " + $(titles[i]).attr('title') );
                //$(titles[i]).append('<span>?</span>');
                $(titles[i]).append('<div class="m-pop"><p class="top">' + $(titles[i]).attr('title') + '</p><p class="bottom"></p></div>');
                //on supprime le title actuel
                $(titles[i]).attr("title","");
                //$(titles[i]).children('span').hover(function() { me.titleOn(this); }, function() { me.titleOff(this) });
                $(titles[i]).hover(function() { me.titleOn(this); }, function() { me.titleOff(this) });
                $(titles[i]).children('div').hide();
            }
        }
        
        //Hover...
        $("#m-menu li").hover(function() {
            $(this).addClass("hover");
        }, function() {
            $(this).removeClass("hover");    
        });
        
        
	},
	
	titleOn: function( obj ) {
	    //Debug.log("title On");
	    $(obj).children('.m-pop').show();
	},
	
	titleOff: function( obj ) {
	    //Debug.log("title Off");
	    $(obj).children('.m-pop').hide();
	}
	

};

var ProgressBar = {
    //La barre de progression et les fonctions qui lui sont associées (on utilise jquery UI)

    pos: new Array(), //position de la barre (entre 0 et 100)
    text: new Array(), //Texte a ajouter aux barres...
    
    init: function() {
        //Initialisation de la progressbar
    
        ce(".progressBar").progressbar({
            value: 0
        });
        
        
        
    },
    
    reset: function( bar ) {
        this.pos[bar] = 0;
        this.display( bar );
    },
    
    set: function( val, max, bar, text ) {
        //Fixe la valeur (en pourcent) de la barre en fonction de la valeur donnée et du maximum
        //val : Valeur ou positionner la barre
        //max : Valeur maximale de la barre
		//bar : numéro de la progressbar
		//text : un éventuel message à afficher
		
		var text = (text == null) ? "" : text;
        this.text[bar] = text;
        
        var pos = (val / max ) * 100;
        this.pos[bar] = pos;
        this.display( bar );
    },
    
    display: function( bar ) {
        //Affiche la barre...
    
        ce("#progress" + bar ).progressbar('option', 'value', this.pos[bar] );
        ce("#progress" + bar + "-deco .val").html( this.text[bar] + " " + Math.ceil(this.pos[bar]) + "%");
    },
    
    remove: function( bar ) {
        ce("#progress" + bar + "-deco").fadeOut();
    },
    
    activate: function( bar ) {
        ce("#progress" + bar + "-deco").fadeIn();    
    }

};

var Status = {
    //Status de l'application (pour afficher le loader)
    
    busy: false, 
	timer: null, //pour désactiver le loader après un petit moment (c'est plus joli)
    actions: new Array(), //Liste des actions en cours
    l: null, // le loader
    
    init: function() {
        //Initialisation du status

        this.l = ce("#cartouche-loader");
    },
         
    start: function( action, loader ) {
        //Démarrage d'une action

        var loader = ( loader == null ) ? true : loader; //Mise par défaut a true

        //Debug.log("--start: " + action);
        
        this.busy = true;
        if( loader ) {
            this.showLoader();
        }
         //on recherche l'action dans la liste pour pouvoir la virer si elle est déjà la 
        var index = jQuery.inArray( action, this.actions );
        if( index != -1 ) {
            this.actions.splice(index,1);
        }
  
        //On enregistre l'action dans la liste des actions en cours
        this.actions.push( action );
        
    },
    
    end: function( action ) {
        //Fin d'une action
    
        //Debug.log("--end: " + action);
        
        //on recherche l'action dans la liste
        var index = jQuery.inArray( action, this.actions );
        if( index != -1 ) {
            this.actions.splice(index,1);
        }
        
        //On vérfie s'il reste des actions actives
        this.pendingActions();
    },
    
    pendingActions: function() {
        //Actions encore active? S'il ne reste plus rien, on vire le loader.

        if(this.actions.length == 0 ) {
            //Debug.log("ready...");
			this.busy == false;
            this.removeLoaderAfterDelay();
        } else {
            //Debug.log("!! " + this.actions );
        }

    },
    
    showLoader: function() {
        //Affichage du loader
    
        clearTimeout( this.timer );
        this.l.show();
    },
    
    removeLoaderAfterDelay: function( delay ) {
        //Lance un timer pour supprimer le loader après un certain délais
    
        var delay = ( delay == null ) ? 50 : delay; //Mise par défaut du délais à 200ms
        clearTimeout( this.timer );
        this.timer = setTimeout( "Status.removeLoader()", delay);
    },
    
    removeLoader: function() {
        //Suppression immédiate du loader
    
        this.l.fadeOut();
    }    
    
};

var Tools = {
    getBasePath: function() {
        return window.location.protocol + '//' + window.location.host;
    }
};

var Chrono = {
    //Chronomère de l'application et les fonctions qui lui sont associées.
    //Attention, pour ne pas trop fausser les mesures, on ne vérifie pas si les compteurs existent!!! donc il faut les lancer avant de les stopper ou de les lire...

    data: new Array(), //Liste des timestamps de départ
    
    start: function( counter ) {
        //Démarrage d'un compteur
        var d = new Date();
        this.data[counter] = new Array();
        this.data[counter]['start'] = d;
    },
    
    stop: function( counter ) {
        this.data[counter]['stop'] = new Date();
    },
    
    inter: function( counter ) {
        //Retourne un temps intermédiaire

        var s = new Date();
        var d = s - this.data[counter]['start'] ;
        //Debug.log("chrono : " + counter + " : " + d );
        return d;
    },
    
    read: function( counter ) {
        var d = this.data[counter]['stop'] - this.data[counter]['start'] ;
        Debug.log("chrono : " + counter + " : " + d );
    },
    
    sr: function( counter ) {
        //stop and read
        
        this.stop( counter );
        this.read( counter );
    }
};

var Debug = {
    
    level: null, //Niveau de débug
    
    init: function() {
        this.level = ce("#m-main").attr("data-debug");
        ce('#log').click(function() {
            //alert("reset");
            Debug.clear();
        });
       
        //this.mouseTracking();
        
    },
    
    mouseTracking: function() {
    
        if( this.level > 0 ) {
            //on traque la souris
            $().mousemove( function(e) {
                var x = e.pageX;
                var y = e.pageY;
                var x1 = x - 272;
                var y1 = y - 105;
                
                ce("#mousePos").html("x:" + x + " y:" + y + "<br>x: " + x1  + " y:" + y1);
            });
        }
        
    },
    
    log: function( msg ) {
        
        if( this.level > 0 ) {
            var t = Chrono.inter("main");
            ce('#log').prepend("<p>@" + t + "ms : <br>" + msg + "</p>");       
        }
        
    },
    
    clear: function() {
        ce('#log').empty();
    },
    
    stop: function() {
        //onFaitToutPlanter();
        throw "exit";
    }
    
};

var Test = {

    init: function() {
        Debug.log("TEST init");   
        
        ce("#test1").click( function() {
            Debug.log("Click1");
			Cache.loadAll("lq");
            return false;
        });

        ce("#test2").click( function() {
            Debug.log("Click2");
			Cache.loadAll("hq");
            return false;
        });

        ce("#test3").click( function() {
            Debug.log("Click3");
			Cache.display(35);
            return false;
        });
        
        ce("#test4").click( function() {
            Debug.log("Click4");
			Cache.display(100);
            return false;
        });
        
        ce("#test5").click( function() {
            Debug.log("Click5");
			Controls.displayStop();
            return false;
        });
        
        ce("#test6").click( function() {
            Debug.log("Click6");
			Controls.displayPlay();
            return false;
        });

    }

};


/////////
// INIT
////////
$(document).ready(App.init);



