/**
*   pour démarrer le chargement des script après le chargement de la page
*/
Event.observe(
	$(window),
	'load',
	function(event){
		charger();
	}
);


var jeux;
/*
*   chargement des scripts
*/
function charger(){
    complement=parseInt($$('table.complement').first().getAttribute('complement').gsub(/.*-([0-9]*)/,"#{1}"));
    jeux=new jeu();//crée le jeu
    window.Element.observe(//idem sur bouton start
        $('start'),
        'click',
        jeux.boutons
    );
}


/**
*   Klass de jeu
*/

jeu=Class.create({
    tableau:[],//array contient les prochaines pieces à tomber.
    nb:0,
    texte:"",
    ok:null,
    figure:0,
    formCour:null,
    formNext:null,
    cases:new Array(),
    formes:[],
    niveau:1,
    point:0,
    ligne:0,
    pause:false,//la partie est en pause?
    fin:true,//partie en cours?
    coulForme:["#0047ff", "#a3a3ff", "#33cc66", "#b7ffb7", "#ffff66", "#ffffcc", "#ffcc99", "#ff6633", "#ff3333", "#ff00ff", "#b80047"],
    //couleurs des formes
    formes:[],//deprecated?
    nbCaseX:6,//nb de cases e largeur
    nbCaseY:15,//nombre de cases en hauteur
    tailleCase:40,//taille de la case
    taille :null,//taille du cube
    rebord:null,//épaisseur du trait
    posx:null,//abscisse de la piece courante
    posy:null,//ordonnée de la pièce courante
    bord:null,//div de jeu
    prochain:null,// td suivant
    pts:0,//nb de points
    
    
    /**
    *   constructeur
    *
    */
    initialize : function(){
        this.coulForm=$R(0,complement).collect(
                function(n){
                    return '000000'+(new Number(Math.floor(n*2047/complement)).toString(16)).gsub(/([a-f0-9])*([a-f0-9])([a-f0-9])([a-f0-9])$/,"#{1}:#{2}:#{3}");})
        for (i=0;i<5;i++){
            this.ajoutePaire();//remplis le tableau de valeur
        }
        this.taille=this.tailleCase + (document.all?0:-2);//taille des cases
        this.rebord = (document.all)?0:2;//taille du rebord
        this.creerGrille();//crée la grille
   },
   
   /**
   *
   *    Ajoute des paires de compléments au tableau
   */
   ajoutePaire : function(){
            var nb=Math.floor(Math.random()*(complement+1));
            this.tableau[this.tableau.size()]=nb;
            this.tableau[this.tableau.size()]=complement-nb;
            this.tableau=this.melange(this.tableau);
   },
   
   /*
   *    melange les pieces
   *
   */
   melange : function(tableau){
        tableau=tableau.sortBy(function(e){return Math.random()});
        return tableau;
   },
   
   /**
   *    crée la grille en reliant les entités html à l'objet
   *
   */
   creerGrille : function(){
        this.prochain=$('next').down('td');//td prochain
        this.bord=$('jeux'); //div contenant la grille de jeu
        this.bord.style.width =this.tailleCase * this.nbCaseX;
        this.bord.style.height = this.tailleCase * this.nbCaseY;
        this.bord.style.backgroundColor = "#8f8f8f";
        this.bord.update(this.creerTable());//remplis le div avec la table de jeu
   },
   
   /**
   *    remplis lbord avec une grille de jeu
   *    return Element table
   *
   */
   creerTable : function(){
        tbl = new Element("table");//crée la table
        tb= new Element("tbody");
        tbl.update(tb);
        tbl.cellSpacing="0";
        tbl.cellPadding="0";
        tbl.width = this.tailleCase * this.nbCaseX;
        tbl.height = this.tailleCase * this.nbCaseY;
        for (rows=0;rows<=this.nbCaseY;rows++){
            row = new Element("TR");
            this.cases[rows]=[];
            for (cols=0;cols<this.nbCaseX;cols++){
                col = new Element("td");
                col.x=cols;//sa  ligne
                col.y=rows;//sa colonne
                col.coord=[col.x,col.y];
                col.className="caseTB";
                col.innerHTML="&nbsp;";
                if(this.nbCaseY==rows){
                    col.className='bordGauche';
                    col.insert("<div class='bordGauche'>&nbsp;"+cols+"</div>");
                }
                row.insert(col);
                this.cases[rows][cols]=col;
            }
            col=(new Element("Td",{class:'bordinferieur'})).insert("<div class='bordInferieur'>&nbsp;"+rows+"</div>");
            row.insert(col).style.height="1px";
            if(this.nbCaseY==rows)row.addClassName('bordinferieur');
            tbl.insert(row);
        }
        return tbl;
   },
   
   /**
   *    Crée le cube suivant
   */
   creerSuivant : function(){//dans formNext
        this.formNext=new cube(this.tableau.pop());//cree un cube avec le dernier élément
        this.formNext.ajouteCellule(this.prochain);//l'ajoute dans l'élément prochain
        if(this.tableau.size()<10){//si lors de la création d'un suivant la taille des valeurs en réserve est <10,on ajoute une paire
            this.ajoutePaire();
        }
   }, 
   
   /**
   *    Crée le cube courant
   */
   creerCourant : function(){//dans formCour
        if(this.formNext){  //si on a un suivant, on le prend pour créer le cube
            this.formCour=this.formNext;
            this.creerSuivant();//on recrée un suivant
        }else{//sinon on en crée un a partir du tableau
            this.formCour=new cube(this.tableau.pop());
        }
        /*
        *   Si la première case est déjà pleine le jeu s'arrête.
        */
        if(this.cases[0][2].down('div')) this.partieFinie();
        //sinon on met la forme courante dans la premiere case
        this.formCour.ajouteCellule(this.cases[0][2]);
   },
   
   /**
   *    Déplace la formCourante denbY vers le bas et de nbX vers la gauche
   *
   */
   deplacerForme : function(nbY, nbX){
        var x,y,courant;
        x=this.formCour.td.x+nbX;
        y=this.formCour.td.y+nbY;
        if(x<0 || y<0 || x>= this.cases[0].size() || y>=this.cases.size()){
            return false;
        } else {
            return this.formCour.ajouteCellule(this.cases[y][x]);
        }
    },
    
    /**
    *   Fais descendre la forme courante
    *   fonction appelée à intervalles réguliers
    */
    partieEnCour : function (){
        var courant;
        if (!this.deplacerForme(1,0)){//si on ne peut déplacer la forme vers le bas 
            courant=this.formCour.td;
            if (!this.formCour.td.y) {//la forme est tout en haut
                this.fin = true;
                clearTimeout(ok);
                clearInterval(this.pts);
                document.main.start.value = "COMMENCER";
                this.partieFinie();
                return;// la partie est finie
            }else{//l'élément est non déplaçable à cause d'une autre ou d'une bordure
                this.verifier_voisins(courant);
                this.creerCourant();
            }
        }
        ok = setTimeout("jeux.partieEnCour()",this.vitesse);// on rappelle la fonction
    },
    
    partieFinie : function(){
                div=new Element('div',{id:"confirm"}).update("<p>La partie est terminée<p>Voulez-vous refaire une partie?<p><input class=recommencer type=button value='Recommencer le jeu' onclick='$(this).up(\"div\").remove();jeux.nouvellePartie();'/><input class=terminé type=button value=\"Non merci!\" onclick='document.location.href=\"..\"'/>");
                $$('body').first().insert(div);
    },
    
    /** 
    *       Vérifie si deux cases forment 10(complement)
    *
    */
    sontComplements : function(td1,td2){
        if(td1 && td2 && td1.down() && td2.down()){
            return td1.down().cube.no+td2.down().cube.no==complement;
        } else{
            return false;
        }
    },
    
    /**
    *   Vérifie si les adjacents de td sont des compléments
    *
    *
    */
    verifier_voisins: function(td){ 
	var flag=null;
        if(this.sontComplements(td,this.suivant(td))){
            this.suivant(td).down().remove()
            td.down().remove()
            flag=true;
        }else  if(this.sontComplements(td,this.precedent(td))){
            this.precedent(td).down().remove();
            td.down().remove();
            flag=true;
        }else  if(this.sontComplements(td,this.superieur(td))){
            this.superieur(td).down().remove();
            td.down().remove();
            flag=true;
        }else  if(this.sontComplements(td,this.inferieur(td))){
            this.inferieur(td).down().remove();
            td.down().remove();
            flag=true;
        }	  
	if(flag){
	    flag=null;
            this.ligne++;
            this.point = this.point + this.niveau;
            this.niveau = Math.floor(this.ligne/20)+1;
            this.vitesse = 800 - (this.niveau * 45)
            this.refaire_tableau();
        }
    },
    
   /**
   *    faire descendre les forme au dessus d'une case vide
   *
   */
    refaire_tableau: function(){
        divs=$$('#jeux div.cube')._reverse();
        divs.each(function(div){    
            div.cube.pose();
        });
    },
    
    /**
    *       appelée par une pression de touche
    *
    *
    */
    verifierActionJoueur: function(ev){
        jeux.bord.scrollTo();
        if (jeux.pause) return;
        window.event=ev;
        var keyPress = document.all?event.keyCode:ev.which; //alert(keyPress);
        if (keyPress == 76||keyPress==37){//flechegauche
            jeux.deplacerForme(0,-1);
        }else if (keyPress == 77||keyPress==39){//flechedroit
            jeux.deplacerForme(0,1);
        }else if (keyPress == 38) {//flechehaut
            //jeux.deplacerForme(-1,0);
        }else  if (keyPress == 40) {//flechebas
            jeux.deplacerForme(1,0);
        }else if (keyPress == 32){//espace
            while(jeux.deplacerForme(1,0)){
            }
        }
        ev.stop();
    },
    
    /**
    *   Mets les données de score à jour
    *
    */
    majPointage: function (){
        document.main.points.value = this.point;//point;
        document.main.niveaux.value = this.niveau;//niveau;
        document.main.lignes.value = this.ligne;//nombre de couples obtenus
    },
    
    help : function (){
        var h = $("aide");
        h.clonePosition($$('table.complement').first());
        if (!this.pause && !this.fin) {
            $('start').click();
        }
        h.show();
    },
    
    
    /**
    *      Débute la partie
    *
    *
    */
    nouvellePartie:function(){
        $$('.cube').invoke('remove')// on efface les cubes sur le tapis
        this.fin=false;//la partie n'est pas finie
        this.posy=-1;//position de la pièce courante (hors jeu)
        this.vitesse=800;//vitesse initiale
        this.niveau=1;//niveau
        this.point=0;//nb de points 
        this.ligne=0;//nb de combinaisons faites
        this.posx = ((this.nbCaseX / 2)-2);//position de depart abscisse
        this.creerSuivant();//crée l'élément suivant
        this.creerCourant();//crée l'élément courant
        this.pts = setInterval("jeux.majPointage()",100);//thread pour mettre à jour les scores
        setTimeout("jeux.partieEnCour()",this.vitesse);//thread pour déplacer les pièces
	document.key.down.focus();//focus sur les touches du clavier
	document.key.down.onkeydown = this.verifierActionJoueur;//si une touche est actionnée on appelle la fonction "verifierActionJoueur"
        window.focus();//focus sur la fenêtre
        jeux.bord.scrollTo();
    },
    
    /*
    *   retourne la case à droite ou false
    */
    suivant : function(td){
        return (td.x+1>=this.nbCaseX)?false:this.cases[td.y][td.x+1];
    },
    
    /*
    *   retourne la case à gauche ou false
    */
    precedent : function(td){
        return (td.x<=0)?false:this.cases[td.y][td.x-1];
    },
    
    /*
    *   retourne la case au dessus ou false
    */
    superieur : function(td){
        return td.y<=0?false:this.cases[td.y-1][td.x];
    },
    
    /*
    *   retourne la case au dessous ou false
    */
    inferieur : function(td){
       return (td.y+1>=this.nbCaseY)?false:this.cases[td.y+1][td.x];
    },
    
    boutons : function(event){
            bouton=event.element();
            if (jeux.pause) {//si le jeu est en pause
                jeux.pause=false;
                ok = setTimeout("jeux.partieEnCour()",jeux.vitesse);// on rappelle la fonction
                bouton.value='PAUSE'
            } else if (bouton.value=='COMMENCER'){//click sur bouton commencer=>débute la partie
                jeux.nouvellePartie();
                bouton.value='PAUSE'
            } else {
                clearTimeout(ok);
                clearInterval(this.pts);
                bouton.value='CONTINUER';
                jeux.pause = true;
            }
    }
})



/**
*
*   Klass permettant de créer les cubes
*
*/
cube=Class.create({
    td:{},
    r:0,
    g:0,
    b:0,
    no:null,
    el:null,//le div à déplacerde cellules en cellules
    /**
    *   Constructeur : 
    *   no nombre à afficher dans le div
    */
    initialize:function(no){
        this.no=no;
        //this.couleur=jeux.coulForme[no];//définie la couleur
        this.el=new Element('DIV');//crée le div
        this.el.addClassName("cube");
        this.el.style.backgroundColor = this.couleur();
        this.el.innerHTML=no;
        this.el.cube=this;
    },
    
    /**
    *   Déplace  le cube dans la cellule td
    *
    */
    ajouteCellule:function(td){
        if(td!=jeux.prochain && td.down())return false;
        td.appendChild(this.el);
        td.update(this.el);
        this.td=td;
        return this;
    },
    
    couleur: function(){
        var c=this.no/complement;
        this.c=c;
        if(c>=0 && c<1/3){
            this.cas=1;
            this.r=255;
            this.b=Math.floor(255*(1-3*c));
            this.g=Math.floor(255*3*c);
        } else if (c<2/3){
            this.cas=2;
            this.b=255;
            this.g=Math.floor(255*(1-3*(c-1/3)));
            this.r=Math.floor(3*(c-1/3));
        }else{
            this.g=255;
            this.cas=3;
            this.r=Math.floor(255*(1-3*(c-2/3)));
            this.b=Math.floor(3*(c-2/3));
        }
        return 'rgb('+this.r+','+this.g+','+this.b+')';
    },
    
    /**
    *  pose le div sur le div imédiatement au dessous
    *
    *
    */
    pose : function(){
        inf=$$('#jeux div.cube').inject(jeux.nbCaseY,function(acc,div){
            if(div.cube.td.x==this.td.x && div.cube.td.y>this.td.y){
                return div.cube.td.y<acc?div.cube.td.y:acc;
            } else {
                return acc;
            }
        },this);
        if(this.td.y!=inf-1){
            this.ajouteCellule(jeux.cases[inf-1][this.td.x]);
            jeux.verifier_voisins(this.td);
        }else{
            return false;
        }
    }
});
