package lecode;

//<editor-fold defaultstate="collapsed" desc="imports">
import donnees.Personne;
import static donnees.Taquin.listeDesPersonnes;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import processing.core.PApplet;
import processing.core.PImage;
//</editor-fold>

public class Sketch extends PApplet {
    
    int DIMCASE=80, NBCASES=4, COTE=DIMCASE*NBCASES, NBDEPMAX=1;
    
    List<Integer> resolution = new LinkedList();int nbpas;
    int index = 0;
    boolean sol = false;
    
    boolean fin = false;
    
    int colClick , ligClick, colVide, ligVide;
    int cpt=0;
    
    int niveau;
    
    long debutTemps; long finTemps;
    
    String nomChoisi; Scanner clavier = new Scanner(System.in);
    
    boolean reussi=false;
    
    PImage img ;
    
    int [][] etat={
                    { 1,  5,   9, 13}, // colonne d'abscisse 0 de la grille
                    { 2 , 6,  10, 14}, // colonne d'abscisse 0 de la grille
                    { 3,  7,  11, 15}, // colonne d'abscisse 2 de la grille
                    { 4,  8,  12,  0}  // colonne d'abscisse 3 de la grille
                  };

    int [][] etatI={
                    { 1,  5,   9, 13}, // colonne d'abscisse 0 de la grille
                    { 2 , 6,  10, 14}, // colonne d'abscisse 0 de la grille
                    { 3,  7,  11, 15}, // colonne d'abscisse 2 de la grille
                    { 4,  8,  12,  0}  // colonne d'abscisse 3 de la grille
                  };
    int i = 0;
    @Override
     public void setup() {
        for (;i < 1; i++) {            
            System.out.println("Veuillez saisir votre pseudo:");
            nomChoisi = clavier.next();
        }
        
        size(COTE,COTE+55);
        frame.getMenuBar();
        img = loadImage("pic.jpg");
        background(220);
        
        reussi= fin = false;
       
        frame.setTitle("CH'TAQUIN LÔ - Niveau " + niveau);
        
        smooth(); 
        
        //quadrillage();
        remplirGrille();
        try {
             lireFichier();
            } catch (IOException ex) {
                Logger.getLogger(Sketch.class.getName()).log(Level.SEVERE, null, ex);
            }        
        debutTemps = System.currentTimeMillis();
     }
    
    @Override
    public void mousePressed() {
       
        colClick=mouseX/DIMCASE; ligClick=mouseY/DIMCASE;
        
        System.out.println("X= "+colClick+" Y= "+ligClick); 
      
        if(abs(colVide-colClick)+abs(ligVide-ligClick)==1){
            cpt++;
            echangerPaveClickCaseVide();bravo();
        }        
    }
    
    @Override
    public void keyPressed(KeyEvent e){
//<editor-fold defaultstate="collapsed" desc="w/ KeyEvent e en paramètre de keyPressed()">
//        //Reboot + plus difficile
//        if (e.getKeyCode() == KeyEvent.VK_R){
//            restart();
//            setup();
//        }
//        //Solution
//        if (e.getKeyCode() == KeyEvent.VK_S){
//            sol = true; Collections.reverse(resolution);
//            nbpas = resolution.size();
//        }
//        //ZOOM avant
//        if(e.getKeyCode() == KeyEvent.VK_D){
//            DIMCASE+=10;
//            COTE=DIMCASE*NBCASES;
//            //this.resize(COTE+=5,COTE+=5);
//            frame.setSize(COTE,COTE+=20);
//            setup();
//        }
//        //ZOOM ARRIÈRE
//        if(e.getKeyCode() == KeyEvent.VK_Q){
//            DIMCASE-=10;
//            COTE=DIMCASE*NBCASES;
//            //this.resize(COTE-=5, COTE-=5);
//            frame.setSize(COTE,COTE-=20);
//            setup();
//            remplirGrille();
//        }
//</editor-fold>
          switch(key){
              case 'r':
                  restart();
                  setup();
              break;
              case 'q':
                  DIMCASE-=10;
                  COTE=DIMCASE*NBCASES;
                  this.resize(COTE-=5, COTE -=5);
                  frame.setSize(COTE,COTE-=20);
                  setup();
                  remplirGrille();
              break;
              case 'd':
                  DIMCASE+=10;
                  COTE=DIMCASE*NBCASES;
                  this.resize(COTE+=5, COTE+=5);
                  frame.setSize(COTE,COTE+=20);
                  setup();
                  remplirGrille();
              break;
              case 's':
                  sol = true;
                  Collections.reverse(resolution);
                  nbpas = resolution.size();
              break;
          }
    }
        
    @Override
    public void draw() {
        if(sol && nbpas > 0){
            delay(10);resolution();
            nbpas--;
            String message;
            effacerPaveBas();
            pavePerdant();
            message="Vous avez perdu !" +
                "\nVous avez mis " + Long.toString((finTemps-debutTemps)/1000) + 
                " secondes avant d'activer la résolution.";
            
        }
        else sol = false;
        if(!fin){
        
         String message;
         if (!reussi){ 
            message="Temps ecoulé: "+Long.toString((System.currentTimeMillis()-debutTemps)/1000)+" secondes\n"+Long.toString(cpt)+" deplacements";
         }
         else{
           effacerPaveBas();
           paveWow();
           message="Bravo !" + "\nScore: " + score((finTemps-debutTemps)/1000,this.NBDEPMAX) + "\nVous avez mis " + Long.toString((finTemps-debutTemps)/1000) + " secondes pour le résoudre";
           fin = true;
         }
       effacerPaveBas();
       fill(0);
       text(message,10,COTE+20);
       paveBas();
       }
    }

    public void quadrillage() {
        stroke(180);
        strokeWeight(1);
        
        for(int nc=0;nc<NBCASES;nc++){ line(nc*DIMCASE,0,nc*DIMCASE,COTE); } // lignes verticales
        for(int nl=0;nl<NBCASES;nl++){ line(0,nl*DIMCASE,COTE,nl*DIMCASE); } //lignes horizontales
    }

    void remplirGrille() {
        
        for( int col=0;col<NBCASES;col++)for( int lig=0;lig<NBCASES;lig++){
        
           String n="";Integer valeur;   
            
           valeur=etat[col][lig];
           
           if(valeur!=0) { 
              
              n=Long.toString(valeur);
              this.dessinerPave(valeur, col, lig);

           }
           else{ colVide=col;ligVide=lig;}
          }  
    }
    
    void effacerPave(int col, int lig){
    
        stroke(220); // gris contour   pave = gris du fond
        fill(220);   // gris interieur pave = gris du fond  
        rect(2+DIMCASE*col,2+DIMCASE*lig,DIMCASE-4,DIMCASE-4,10,10);

        fill(220);   // couleur texte= couleur du fond     
        text("",col*DIMCASE+DIMCASE/2-2,lig*DIMCASE+DIMCASE/2-2);  
    }
    
    void dessinerPave(int val,int col, int lig){
        stroke(180);         // gris du contour du pave
        PImage pim = img.get(xA(n1(val)), yA(n1(val)), DIMCASE, DIMCASE);
        image( pim,DIMCASE*col,DIMCASE*lig);
        fill(0,0,0);  
    }
        
    void echangerPaveClickCaseVide() {
       
        etat[colVide][ligVide]=etat[colClick][ligClick];
        String n=Long.toString(etat[colVide][ligVide]);
        int val=(etat[colVide][ligVide]);
        dessinerPave(val,colVide,ligVide);
        
        etat[colClick][ligClick]=0;
        colVide=colClick;ligVide=ligClick;
        effacerPave(colVide,ligVide);
    }
    
    public void deplacerCaseVide(int dir){
        // dir  0:nord 1:Est 2: Sud 3:Ouest
        
        System.out.println(dir);
        
        switch ( dir){
        
            case 0: ligClick=ligVide-1;colClick=colVide; break;
            case 1: colClick=colVide+1;ligClick=ligVide; break;
            case 2: ligClick=ligVide+1;colClick=colVide; break;
            case 3: colClick=colVide-1;ligClick=ligVide; break;
        }
        echangerPaveClickCaseVide();
        resolution.add(dir);
    }

    void melanger() {
        
        int nDep=0;
        int dirPred=4;
        
        while(nDep<=NBDEPMAX){
        
            int n= (int) random(4);
            
            if(  !(ligVide==0&&n==0 || ligVide==3&&n==2  || colVide==0&&n==3 || colVide==3&&n==1)  ){
             
             if( !(dirPred==0&&n==2 || dirPred==2&&n==0 || dirPred==1&&n==3 || dirPred==3&&n==1  ) ){
                     
                deplacerCaseVide(n);nDep++;dirPred=n; 
             }    
            
            }
        }
    }
    
    void bravo() {
        int n=0;
        
        for(int nc=0;nc<NBCASES;nc++)  for(int nl=0;nl<NBCASES;nl++){
         
            if (etat[nc][nl]== etatI[nc][nl]) n++;
        } 
        
        if(n==NBCASES*NBCASES){
            reussi=true;
            finTemps = System.currentTimeMillis();
            joueurs();
            try {
                remplirFichier();
            } catch (IOException ex) {
                Logger.getLogger(Sketch.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    } 
    
    void paveBas(){
        noStroke();
        fill(0,0,54,20);
        rect(2,COTE+2,
                COTE-4,                    
                50,
                10,10
                );
    }
    
    void effacerPaveBas(){
        noStroke();
        fill(220);
        rect(2,COTE+2,
                COTE-4,                    
                50,
                10,10
                ); 
    }
     
    void paveWow(){
        noStroke();
        fill(0,54,0,200);
        rect(4,COTE+2,COTE-4,50,10,10);
    }
    
    void pavePerdant(){
        noStroke();
        fill(0,54,0,200);
        rect(4,COTE+2,COTE-4,50,10,10);
    }
     
    public void resolution(){
        switch(this.resolution.get(index)){
            
            case 0 : deplacerCaseVide(2);break;
            case 1 : deplacerCaseVide(3);break;
            case 2 : deplacerCaseVide(0);break;
            case 3 : deplacerCaseVide(1);break;
        }
        index++;
        pavePerdant();
    }
     
    public long score(long temps,long nbDep){
        //666-(nbDeplacement*1.1)-(temps*1.5)+(niveau*1.3)
         long score = (long)100-nbDep-temps;
        
         return score;
    }
    
     public void joueurs(){
        //On créé le joueur
        Personne pseudo = new Personne();
        pseudo.prenom = nomChoisi;
        pseudo.niveau = niveau;
        pseudo.score = score((finTemps-debutTemps)/1000,this.NBDEPMAX);
        listeDesPersonnes.add(pseudo);
    }
     
    /**
     *
     * @throws IOException
     */
    public void remplirFichier() throws IOException{
         BufferedWriter sortie = new BufferedWriter(new FileWriter("pseudo.txt",true));
         for (Personne p : listeDesPersonnes){
             sortie.write(p.prenom);sortie.write(" ");
             sortie.write(new Long(p.niveau).toString());sortie.write(" ");
             sortie.write(new Long(p.score).toString());sortie.write(";");
             sortie.newLine();
         }
         sortie.close();
     }
     
     public void lireFichier() throws IOException {
         BufferedReader entree = new BufferedReader(new FileReader("pseudo.txt"));
         System.out.println("Liste des joueurs :");
         
         String ligne = entree.readLine();
         while (ligne != null){
             String[] infos = ligne.split(";");
             
             for(String s : infos){
                 System.out.printf("%-20s",s);
             }
             
             System.out.println();
             
             ligne = entree.readLine();
         }
         System.out.println();
     }
     
     public void afficherJoueurs(){
         for(Personne p : listeDesPersonnes){
             p.afficher();
         }
         
     }
     
     public int xA(int n){
        return (n%NBCASES)*DIMCASE;
     }
    
     public int yA(int n){
        return(n/NBCASES)*DIMCASE;
     }
    
     public int n1(int n){
        return (n+NBCASES*NBCASES-1)% ( NBCASES*NBCASES);    
     }
     
     public void restart() {
        NBDEPMAX++;
        melanger();

        cpt=0;
        debutTemps = System.currentTimeMillis();
        niveau++;
        frame.setTitle("TAQUIN - Niveau " + niveau);
    }
}
