class Personnage {
  
  
  // 0-1:normalR  2-3:normalL  4-5:rightUp 6-7:rightDown 8-9:leftUp  10-11:leftDrown 12-13:UpJump 14-15:RightJump 16-17:LeftJump 18:RightDead 19:LeftDead
  //etat : 0         1            2            3              4             5            6               7               8              9          10
  
  String[] perNames =   { "lizRight1.png", "lizRight2.png" , "lizLeft1.png", "lizLeft2.png" , "lizRightUp1.png" , "lizRightUp2.png" , "lizRightDown1.png" , "lizRightDown2.png", "lizLeftUp1.png", "lizLeftUp2.png", "lizLeftDown1.png", "lizLeftDown2.png", "lizUpJump.png", "lizUpJump.png", "lizRightJump.png", "lizRightJump.png", "lizLeftJump.png", "lizLeftJump.png", "lizRightDead.png", "lizLeftDead.png"    };
  PImage[] animePer = new PImage[ perNames.length ];          // liste des images pour le lazard au repos ( une liste de noms suivie d'une liste d'objet image );
  
  //manger : 0-1:normalR  2-3:normalL  4-5:rightUp(UpJumpRight) 6-7:rightDown  8-9:leftUp(UpJumpLeft)  10-11:leftDrown  12-13:UpJump    14-15:RightJump   16-17: LeftJump    18:normalR   19:normalL
  //etat :     0             1             2                         3               4                        5               6                7                  8            9              10
  
  String[] mangeNames = { "lizRight3.png", "lizRight4.png" , "lizLeft3.png", "lizLeft4.png" , "lizRightUp3.png" , "lizRightUp4.png" , "lizRightDown3.png" , "lizRightDown4.png", "lizLeftUp3.png", "lizLeftUp4.png", "lizLeftDown3.png", "lizLeftDown4.png", "lizRightUp3.png", "lizRightUp4.png", "lizRightJump3.png", "lizRightJump4.png", "lizLeftJump3.png", "lizLeftJump4.png", "lizRight3.png", "lizLeft4.png"          };
  PImage[] animeMange = new PImage[ mangeNames.length ];      // liste des images pour le lezard entrain de manger ( une liste de noms suivie d'une liste d'objet image );
  
  int frame = 0;                                              // variable pour selectionner l'image a afficher;
  
  PVector pos, centerImage, hitBox;                        // vecteur pour la position (centre) du personnage | vecteur pour le centre de l'image a afficher(centre) | Vecteur pour la taille de la hitBox
  PVector vit;                                                // Vecteur vitesse pour gerer le mouvement du personnage
  PVector gravite;                                            // Vecteur de gravité ( force appiliquer au vecteur vitesse ) 
  float hautHit = 15;                                         // hauteur de la hitBox
  float largHit = 36;                                         // largeur de la hitBox
  
  boolean left, right, up, down, space;                       // interrupter pour les touches claviers
  boolean mangeOn, sautOn, fallOn, rightLock, leftLock, dead, onArbre; // interrupter pour détecter l'état du personnage
  boolean actif = true, graviteOn = true;                     // interrupter On/Off gobale | interrupter gravite
  int etat = 0;                                               // variable pour selectionner l'état du personnage
  boolean sonOk;
  float vitSaut = 0;                                         // variable de la force en y du saut
  
  float temp;                                                 // variable pour stoquer le debut du cronometre
  float tempo = 100;                                          // variable qui déinie le rythme entre chaque nouvelle mesure
  
  float vitesse = 4;
  
  Personnage(  ) {                                            // constructor Objet Personnage | initialisation des objet/variable
    
    pos = new PVector ( 100, 400 );                           // création des vecteurs 
    centerImage = new PVector ( -15, 0 );
    vit = new PVector ( 0, 0 );
    gravite = new PVector ( 0, 4 );
    hitBox = new PVector ( largHit, hautHit );
    
    for ( int i = 0; i < perNames.length; i ++ ) {            // création des images en passant par une boucle qui lie chaque noms de la liste
      String perName = perNames[i];
      animePer[i] = loadImage(perName);
    }
    for ( int i = 0; i < mangeNames.length; i ++ ) {
      String mangeName = mangeNames[i];
      animeMange[i] = loadImage(mangeName);
    }
  }
  
  //----------------
  
  void display() {                       // fonction affichage du personnage
      etat();                            // fonction qui détermine l'état du personnage
      animation( etat );                 // fonction qui détermine le contenue des etats ( image/statut )
      /*
      push();                            // ensemble pour afficher la hitBox du personnage
      rectMode(CENTER);
      noStroke();
      fill(0, 200, 0);
      ellipse(pos.x + centerImage.x, pos.y + centerImage.y, 3, 3);
      stroke( 0 );
      fill( 170, 30, 30, 100 );
      rect( pos.x , pos.y , hitVector.x, hitVector.y );
      pop();
      */
  }
  
  //----------------
  
  void update() {                // fonction qui met a jour le personnage
  }
  
  //----------------
  
  void etat() {
    
                                            // fonction qui détermine le changement d'état
    if ( onArbre ) {
      if ( up ) {
        if ( etat == 2 || etat == 0 || etat == 6 || etat == 7 || etat == 3 || right ) {
          etat = 2;
          graviteOn = false;
          fallOn = false;
        }
        if ( etat == 4 ||etat == 1 || etat == 8 || etat == 5 || left ) {
          etat = 4;
           graviteOn = false;
           fallOn = false;
        }
      }
      if ( down ) {
        if ( etat == 3 ||etat == 2 || right ) {
          etat = 3;
           graviteOn = false;
           fallOn = false;
        }
        if ( etat == 5 ||etat == 4 || left ) {
          etat = 5;
           graviteOn = false;
           fallOn = false;
        }
      }
      if ( !up && !down ) {
        if ( right ) {
          etat = 7;
          onArbre = false;
           graviteOn = true;
        }
        if ( left ) {
          etat = 8;
          onArbre = false;
          graviteOn = true;
        }      
      }
    }
      
    if ( !onArbre ) {
      if ( (!rightLock && etat == 2 )|| (!rightLock && etat== 3 )) {
        etat = 6;
        sautOn = true;
        fallOn = true;
      }
      if (( !leftLock && etat == 4 )|| (!leftLock && etat== 5) ) {
        etat = 6;
        sautOn = true;
        fallOn = true;
      }
    if ( right && rightLock ) {
       if ( vit.x >= 12 ) {
          liz.rightLock = false;
          fallOn = true;
          etat = 7;
        }
    }
    if ( left && leftLock ) {
       if ( vit.x <= -12 ) {
          liz.leftLock = false;
          fallOn = true;
          etat = 8;
        }
    }
    if ( !right && rightLock ) {
          rightLock = false;
          fallOn = true;
          etat = 7;
    }
    if ( !left && leftLock ) {
          leftLock = false;
          fallOn = true;
          etat = 8;
    }
    if ( !fallOn ) {
      if ( etat == 6 || etat == 7 ) {
      etat = 0;
      frame = 0;
      }
      if ( etat == 8 ) {
        etat = 1;
        frame = 3;
      }
    }
    if ( fallOn ) {
      if ( up ) {
        etat = 6;
      }
      if ( right ) {
        etat = 7;
      }
      if ( left ) {
        etat = 8;
      }
    }
    if ( !sautOn && !fallOn && !rightLock && !leftLock ) {
      if ( right ) {
        etat = 0;
      }
      if ( left ) {
        etat = 1;
      }
    }
    if ( rightLock ) {
      if ( right ) {
        if ( etat > 3 || etat < 2 ) {
          etat = 2;
        }
        if ( etat == 2 ) {
          etat = 2;
        }
        if ( etat == 3 ) { 
          etat = 3;
        }
      }
      if ( right ) {
      }
      if ( up ) {
        etat = 2;
      }
      if ( down ) {
        etat = 3;
      }
    }
    if ( leftLock ) {
      if ( left ) {
        if ( etat < 4 || etat > 5 ) {
          etat = 4;
        }
        if ( etat == 4 ) {
          etat = 4;
        }
        if ( etat == 5 ) { 
          etat = 5;
        }
      }
      if ( left ) {
      }
      if ( up ) {
        etat = 4;
      }
      if ( down ) {
        etat = 5;
      }
    }
    }
    if ( dead ) {
      if ( etat == 0 || etat == 2 || etat == 3 || etat == 4 || etat == 6 || etat == 7 || etat == 9 ) {
        etat = 9;   
      } else etat = 10;
    }
    
  }
  
  //-----------------
  
  void deplacement( Map niveau,  Personnage person, Satiete vie) {      // fonction qui détermine le déplacement du personnage
    vit.set( 0, 0 );
    
    if ( !mangeOn ) {
    if ( etat == 0 || etat == 1 ) {    // etat normal droite/gauche
      if ( right ) {
        vit.add( vitesse, 0 );
      }
      if ( left ) {
        vit.add( -vitesse, 0 );
      }
      if ( up && !sautOn && !onArbre ) {
         
        sautOn = true;
        fallOn = true;
        vitSaut = -12;
      }
      if ( down ) {
      }
    }
    if ( etat == 6 || etat == 7 || etat == 8 ) {      // etat saut
      if ( right ) { 
        vit.add( vitesse, 0 );
      }
      if ( left ) {
        vit.add( -vitesse, 0 );
      }
      if ( up ) {
      }
      if ( down ) {
      }
    }
    if ( etat == 2 || etat == 3 ) {        // etat rightLock droite
      if ( !onArbre ) {
        if ( right ) { 
          vit.add( 12, 0 );  // ou 19 ?
        }
      }
      if ( onArbre ) {
        if ( right ) { 
          vit.add( vitesse , 0 );  // ou 19 ?
        }
      }
      if ( left ) {
        vit.add( -vitesse, 0 );
      }
      if ( up ) {
        vit.add( 0, -vitesse );
      }
      if ( down ) {
        vit.set( 0, vitesse );
      }
    }
    if ( etat == 4 || etat == 5 ) {        // etat leftLock gauche
      
      if ( right ) { 
        vit.add( vitesse, 0 );
      }
      if ( !onArbre ) {
        if ( left ) {
          vit.add( -12, 0 );
        }
      }
      if ( onArbre ) {
        if ( left ) {
          vit.add(-vitesse, 0 );
        }
      }
      if ( up ) {
        vit.add( 0, -vitesse );
      }
      if ( down ) {
        vit.set( 0, vitesse );
      }
    }
                       // si saut lire la fonction du saut
    saut();      
    gravite( niveau , person, vie );                     // fonction gravité
    collision( niveau , person , vie );          // fonction qui corrige la vitesse selon les collisions de la Map
    }
    if ( vit.x >= 11 && vit.x <= -11 ) {
      vit.x = 0;
      fallOn = true;
    }
    if ( etat ==9 || etat == 10 ) {        // etat mort droite / gauche
      if ( space ) {                       // fonction reset si mort
        reset();
      }
    }
    if ( etat == 0|| etat == 1 ) {         // si etat normal
      if ( vit.y > 1 ) {                   // et si personnage va déssendre
        fallOn = true;                     // il est entrain de tomber
      }
    }
    niveau.deplacement( person ); 
    pos.add( vit );                        // ajouter la vitesse a la position du personnage
    liz.onArbre = false;
    niveau1.correction( pos, hitBox );  // correction de la position du personnage selon les bloc de la map ( sécurité pour éviter que le Personnage entre dans un bloc et passe au travers la fonction collision()
  }
  
  //----------------
  
  void saut() {                      // fonction pour la mechanique du saut //// désactiver la gravité
    if ( sautOn) {                // si en cour de saut
      graviteOn = false;
      if ( !up && vitSaut < -5 ) {
        vitSaut = -2.5;
      }
      vit.add( 0, vitSaut );     // ajouter la vitesse de saut a la vitesse du personnage  
      vitSaut += 0.5;               // diminier la vitesse de saut
      if (vitSaut > 5  ) {           // si la vitesse du saut est negative  /// désactiver saut
        sautOn = false;                // bloquer la vitesse de saut a -1
        graviteOn = true;
      }
    }
  }

  //----------------
  
  void collision( Map niveau , Personnage person, Satiete vie  ) {    // fonction qui rassemble toute les collisions potentiel du personnage
    niveau.collision( pos, vit , hitBox, niveau, person, vie );    // collision par rapport au bloque de la map
                          // fonction qui deplace la map si le personnage se deplace   //// changer de place ( source de beug );
    limiteEcran( pos, vit, hitBox );                 // fonction qui limite le personnage au borne de l'écran
  }
  
  //----------------
    
  void limiteEcran( PVector pos, PVector vit, PVector hitBox ) {         // fonction qui limite la vitesse du personnage au limite de l'ecran
   if ( pos.x + vit.x <= 0 + hitBox.x / 2 ) {
        vit.x = 0 + hitBox.x / 2 - pos.x;                                             // si le personnage va au dela de l'écran il est désactivé //// probleme a changer
    }
    if ( pos.x + vit.x >= width - hitBox.x / 2 ) {
        vit.x = width - hitBox.x/2 - pos.x;
        if ( !dead ) {
          bisousOn = false;
          point.end = point.score;
          page = 3;
        }
    }
    if ( pos.y + vit.y >= height - hitBox.y / 2 + 30 ) {
        vit.y = height - hitBox.y/2 - pos.y + 30;
        if ( !liz.dead ) {
          sonOver.play();
        }
        actif = false;
        dead = true;
    }
    //if ( pos.y + vit.y <= 0 + hitBox.y/2 - 30 ) {
    //    vit.y = 0 + hitBox.y/2 - pos.y;
    //}
  }
  
  //----------------
  
  void gravite(Map niveau, Personnage person, Satiete vie ) {                  // fonction qui applique la gravite
    gravite.set( 0, 6);                        // définie qui détermine la gravite a 6
    
    niveau.collision( pos, gravite, hitBox, niveau, person, vie); // vérifie que la gravité ne fait pas entrer dans un bloc de la map //// pas efficace a cette endroit changer
    
    if ( graviteOn ) {                        // si la gravite a active
    vit.add(gravite);                         // appliquer la gravité a la vitesse du personnage
    }
  }
  
  //----------------
  
  void PkeyPressed() {         // fonction qui active les commande en fonction des touches
    if ( actif) {
      if ( keyCode == 39 ) {
        right = true;
      }
      if ( keyCode == 37 ) {
        left = true;
      }
      if ( keyCode == 38 ) {
        up = true;
        if ( etat == 0 || etat == 1 ) {
           if ( !sonOk ) {
              sonSaut.play();
              sonOk = true;
            }          // jouer le son du saut                //// mal placé a clarifier
        }
          if ( sautOn || fallOn ) { // et si en cour de saut ou de chute
            if ( !onArbre ) {
            up = false;    
            }// la commande up ne s'active pas
          }
         
      }
      if ( keyCode == 40 ) {
        down = true;
      }
    } 
    if ( keyCode == 32 ) {
      space = true;
    }
  }
  
  //----------------
  
  void PkeyReleased() {                    // fonction qui désactive les commande en fonction des touches ( permet de maintenir enfoncer les touche );
      if ( keyCode == 39 ) {
        right = false;
      }  
      if ( keyCode == 37 ) {
        left = false;
      }
      if ( keyCode == 38 ) {
          up = false;  
      }
      if ( keyCode == 40 ) {
        down = false;
      }
      if ( keyCode == 32 ) {
        space = false;
      }
  }
  
  //----------------
  
  void animation( int etat ) {           // fonction qui paramtre les etat et jou les animations //// pas évident s'épparer les deux fonction, plus simple
    if ( etat == 0 ) {                  // si etat normal droite
      graviteOn = true;                 // gravite est appliqué
      hitBox.set(36, 15);            // la hitBox fait 36 de large et 15 de hauteur
      centerImage.set( -15, 0 );        // le centre de l'image est décaller de -15 sur x par rapport a position Personnage
      anime ( right, 0, 1, 0, 4 );      // jouer animation ( si commmande droite actif ( pas d'animation si a l'arret ) | jouer la frame 0 et 1 | décaller image de 4 en y par rapport a centreImage
    }
    if ( etat == 1 ) {
      graviteOn = true;
      hitBox.set(36, 15);
      centerImage.set( 15, 0 );
      anime( left, 2, 3, 0, 4 );
    } 
    if ( etat == 2 ) {
      graviteOn = false;
      vitSaut = 0;
      sautOn = false;
      fallOn = false;
      hitBox.set(15, 36);
      centerImage.set( 0, 15 );
      anime(up, 4, 5, 4, 0 );
    }
    if ( etat == 3 ) {
      graviteOn = false;
      vitSaut = 0;
      sautOn = false;
      fallOn = false;
      hitBox.set(15, 36);
      centerImage.set( 0, -15 );
      anime(down, 6, 7, 4, 0 );
    }
    if ( etat == 4 ) {
      graviteOn = false;
      vitSaut = 0;
      sautOn = false;
      fallOn = false;
      hitBox.set(15, 36);
      centerImage.set( 0, 15 );
      anime(up, 8, 9, -2, 0 );
    }
    if ( etat == 5 ) {
      graviteOn = false;
      vitSaut = 0;
      sautOn = false;
      fallOn = false;
      hitBox.set(15, 36);
      centerImage.set( 0, -15 );
      anime(down, 10, 11, -2, 0 );
    }
    if ( etat == 6 ) {
      graviteOn = true;
      hitBox.set(15, 36);
      centerImage.set( 2, 18 );
      anime(fallOn, 12, 13, 0, 0 );
    }
    if ( etat == 7 ) {
      graviteOn = true;
      hitBox.set(36, 15);
      centerImage.set( 0, 15 );
      anime(right, 14, 15, -4, 0 );
    }
    if ( etat == 8 ) {
      graviteOn = true;
      hitBox.set(36, 15);
      centerImage.set( 0, 15 );
      anime(left, 16, 17, 4, 0 );
    }
    if ( etat == 9 ) {
      graviteOn = true;
      hitBox.set(36, 15);
      centerImage.set( -15, 0 );
      anime(dead, 18, 18, 4, 0 );
    }
    if ( etat == 10 ) {
      graviteOn = true;
      hitBox.set(36, 15);
      centerImage.set( 15, 0 );
      anime(dead, 19, 19, 4, 0 );
    }    
    niveau1.correction(pos, hitBox);             // corriger la position du personnage si la hitBob rentre dans bloc apres changement de sa taille
  }
  
  //----------------
  
  void anime( boolean touche, int frameMin, int frameMax, int x, int y ) {  // fonction qui joue une animation
    if ( !mangeOn ) {                                        // si personnage n'est pas entrain de manger
      tempo = 100;                                             // temps entre chaque image  en ms
      if ( frame < frameMin || frame > frameMax ) {            // et si frame n'est pas compris entre frameMin et frameMax
        frame = frameMin;                                      // alors frame devien frameMin ( entre dans l'intervale de l'animation);
      }      
      if ( touche ) {                                          // si la cammande touche est activer
        if ( time > temp + tempo ) {                             // et que lemps(horgloge interne) est supérieur a la limite du crono ( temps enregistrer + tempo );
          temp = time;                                           // alors enregistrer le temps ( début crono );
          frame++;                                               // frame suivante 
          if ( frame < frameMin || frame > frameMax ) {            // si  frame est sortie de l'intervale
            frame = frameMin;                                      // revenir la premiere frame de l'animation ( boucle debut | fin | debut | fin | ect ...)
          }
        }
      }
      push();                                                   // insoler réglage ( crée une bulle isolé );
      imageMode( CENTER );                                      // mode d'affichage des images, center par rapport a un point
      image(animePer[ frame ], pos.x + centerImage.x + x, pos.y + centerImage.y + y ); // afficher l'image[ frame] la position du personnage + centerImage + décallage
    }  
    if ( mangeOn ) {
      actif = false;            //// doit pouvoir etre changer de place
      tempo = 200;
      if ( frame < frameMin || frame >frameMax ) {
        frame = frameMin;
        temp = time;
      }
      push();
      imageMode( CENTER );
      image(animeMange[ frame ], pos.x + centerImage.x + x, pos.y + centerImage.y + y );
      if ( time > temp+tempo ) {
        temp = time;
        frame++;
        if ( frame > frameMax ) {
        mangeOn = false;              //// changer de place ( crée des probleme );
        actif = true;
        }
      }
    }
    pop();
  }


  void reset() {   // fonction reset ; retour des paramettre a 0;
    time = 0;
    time = millis();
    point.start = time;
    point.actif = true;
    pos.set( 100, 400 );
    niveau1.reset();
    dead = false;
    actif = true;
    etat = 0;
    life.satiety = 12;
    life.over = false;
    sonP.stop();
    sonMazon.stop();
    sonV.stop();
    sonSatiete.stop();
    sonSatiete.loop();
    sonSaut.stop();   
  }
  
}
