#include <FastLED.h>

#include <cpp_compat.h>


#include <FastLED.h>
#define NUM_LEDS1 40
#define NUM_LEDS2 5
#define NUM_LEDS3 5


CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
CRGB leds3[NUM_LEDS3];
const byte N1[1] = {0};// Leds allumÃ©s pour produire le score 1
const byte N2[2] = {0,1};// Leds allumÃ©s pour produire le score 2
const byte N3[3] = {0,1,2}; // Leds allumÃ©s pour produire le score 3
const byte N4[4] = {0,1,2,3}; // Leds allumÃ©s pour produire le score 4
const byte N5[5] = {0,1,2,3,4}; // Led allumées pour produire le score 5


// Parametre du jeu

byte gamestate = 0;
byte start;
byte redscore = 0;
byte greenscore = 0;
char i;
char m;
int x;
char ledposition;
bool redpush = 0;
bool greenpush = 0;
bool greenwin = 0;
bool redwin = 0;
bool dooncered = 0;
bool dooncegreen = 0;
unsigned long starttime;
unsigned long currenttime;
unsigned int waittime = 60;
float exchange = 0;
float exchangeON = 1;

void RED() {
  if (dooncered == 0) {
    switch (gamestate) {
      case 0:
        gamestate = 1;
        start = 0;
        dooncered = 1;
        break;
      case 1:
        if (start == 1) {
          redpush = 1;
        }
        dooncered = 1;
        break;
      case 2:
        redpush = 1;
        dooncered = 1;
        break;
    }
  }
}

void GREEN() {
  if (dooncegreen == 0) {
    switch (gamestate) {
      case 0:
        gamestate = 1;
        start = 1;
        dooncegreen = 1;
      case 1:
        if (start == 0) {
          greenpush = 1;
        }
        dooncegreen = 1;
        break;
      case 3:
        greenpush = 1;
        dooncegreen = 1;
        break;
    }
  }
}

void setup() {
  FastLED.addLeds<WS2812B, 8, GRB>(leds1, NUM_LEDS1); // Guirlande de jeu dÃ©clarÃ© et branchÃ© en pin 8
  FastLED.addLeds<WS2812B, 9, GRB>(leds2, NUM_LEDS2);
  FastLED.addLeds<WS2812B, 10, GRB>(leds3, NUM_LEDS3);
  pinMode(2, INPUT_PULLUP);// Bouton joueur 1
  pinMode(3, INPUT_PULLUP); // Bouton joueur 1=2
  attachInterrupt(0, RED, FALLING);
  attachInterrupt(1, GREEN, FALLING);
  
  
  
}

void loop() {
   
  
  switch (gamestate) {
    case 0: 
      leds1[0].setRGB(255, 0, 0);// Leds allumÃ©es au dÃ©mmarage  joueur 1// (R,G,B) sont la quantitÃ© de couleurs pour chaque couleurs possibles Rouge(red)/Vert(Green)/Bleu (Blue)  
      leds1[1].setRGB(255, 0, 0);
      leds1[3].setRGB(255, 0, 0);
      leds1[2].setRGB(255, 0, 0);
      leds1[4].setRGB(255, 0, 0);
      leds1[37].setRGB(255, 0, 0);  // Leds allumÃ©es au dÃ©mmarage joueur 2 // (R,G,B) sont la quantitÃ© de couleurs pour chaque couleurs possibles Rouge(red)/Vert(Green)/Bleu (Blue
      leds1[38].setRGB(255, 0, 0);
      leds1[39].setRGB(255, 0, 0);
      leds1[36].setRGB(255, 0, 0);
      leds1[35].setRGB(255, 0, 0);
      FastLED.show();
      break;
      
 

    case 1:
      showscore();
      if (start == 0) {
        redtogreenstart();
      }
      else {
        greentoredstart();
      }
      break;
    case 2:
      if (ledposition > 34) {
        dooncered = 0;
        greentored();
      }
      else {
        redwin = 1;
        exchange=0;
        gamestate = 4;
      }
      break;
    case 3:
      if (ledposition < 5) {
        dooncegreen = 0;
        redtogreen();
      }
      else {
        greenwin = 1;
        byte exchange=0;
        gamestate = 4;
      }
      break;
    case 4:
      waittime = 60;
      if (redwin == 1) {
        redwin = 0;
        redscore++;
        if (redscore == 5) { //limite score
          redwinanimation();
          gamestate = 0;
          redscore = 0;
          greenscore = 0;
          dooncered = 0;
          dooncegreen = 0;
          leds2off();
          leds3off();
        }
        else {
          showscore();
          start = 1;
          gamestate = 1;
          dooncered = 0;
        }
      }
      if (greenwin == 1) {
        greenwin = 0;
        greenscore++;
        if (greenscore == 5) { // limite score
          greenwinanimation();
          gamestate = 0;
          redscore = 0;
          greenscore = 0;
          dooncered = 0;
          dooncegreen = 0;
          leds2off();
          leds3off();
        }
        else {
          showscore();
          start = 0;
          gamestate = 1;
          dooncegreen = 0;
        }
      }  
      break;
  }
}

void redtogreenstart() { 
  dooncered = 0;
  float exchange=0;
  for (i = 0; i < NUM_LEDS1; i++) { // Jeu en cours - Cas quand rouge commence premier echange
    leds1off();
    if (i < 5) {
      leds1[i].setRGB(255, 0, 0); // Rouge si led entre 1 et 5
    }
    if (i >= 5 && i < 10) {
      leds1[i].setRGB(255, 255, 0); //Jaune  si led entre 5 et 10
    }
    if (i >= 10 && i < 30) {
      leds1[i].setRGB(0, 255, 0); //Vert si led entre 10 et 30
    }
    if (i >= 30 && i < 35) {
      leds1[i].setRGB(255, 255, 0); //Jaune si led entre 30 et 35
    }
    if (i > 34) {
      leds1[i].setRGB(255, 0, 0);// Rouge si supÃ©rieur Ã  34
    }
    FastLED.show();
    if (greenpush == 1) {
      ledposition = i;
      i = NUM_LEDS1;
      gamestate = 2;
      greenpush = 0;
      
 
    }
    pause();
    if (i == 39) {
      redwin = 1;
      gamestate = 4;
    float exchange = 0;
    }
  }
}

void greentoredstart() {  // Jeu en cours - Cas quand vert commence premier echange
  dooncegreen = 0;
  float exchange=0;
  
  for (i = 39; i > -1; i = i - 1) {
    leds1off();
    if (i < 5) {
      leds1[i].setRGB(255, 0, 0); // Rouge si led entre 1 et 5
    }
    if (i >= 5 && i < 10) {
      leds1[i].setRGB(255, 255, 0); // Jaunne si led entre 5 et 10
    }
    if (i >= 10 && i < 30) {
      leds1[i].setRGB(0, 255, 0);// Vert si led entre 10 et 30
    }
    if (i >= 30 && i < 35) {
      leds1[i].setRGB(255, 255, 0);// Jaune si led entre 30 et 35
    }
    if (i > 34) {
      leds1[i].setRGB(255, 0, 0);// Rouge si led entre 1 et 5
    }
    FastLED.show();
    if (redpush == 1) {
      ledposition = i;
      i = -1;
      gamestate = 3;
      exchange+=exchangeON;
      redpush = 0;
      
    }
    pause();
    if (i == 0) {
      greenwin = 1;
      float exchange = 0;
      gamestate = 4;
    }
  }
}

void redtogreen() {
  if (waittime == 0) { //Vitesse de dÃ©part. Plus Le chiffre est negatif, -10 ou -30 par exemple, plus le jeu va vite
  }
  else {
    waittime = waittime - 2 ; // Plus le chiffre est negatif, plus le jeu accelerera entre chaque echange
  }
  for (i = ledposition; i < NUM_LEDS1; i++) {
    leds1off();
    if (i < 5) {
      leds1[i].setRGB(255, 0, 0);// Rouge si led entre 1 et 5
    }
    if (i >= 5 && i < 10) {
      leds1[i].setRGB(255, 255, 0); //Jaune si led entre 5 et 10
    }
    if (i >= 10 && i < 30) {
      leds1[i].setRGB(0, 255, 0);// vert si led entre 10 et 30
    }
    if (i >= 30 && i < 35) {
      leds1[i].setRGB(255, 255, 0);// Jaune si led entre 30 et 35
    }
    if (i > 34) {
      leds1[i].setRGB(255, 0, 0); //Rouge si led entre 35 et 40
    }
    FastLED.show();
    if (greenpush == 1) {
      ledposition = i;
      i = NUM_LEDS1;
      gamestate = 2;
      greenpush = 0;
      exchange+=exchangeON;
    }
    pause();
    if (i == 39) {
      redwin = 1;
      float exchange = 0;
      gamestate = 4;
    }
  }
}

void greentored() {
  if (waittime == -20) {
  }
  else {
    waittime = waittime - 4;
  }
  for (i = ledposition; i > -1; i = i - 1) {
    leds1off();
     if (i < 5) {
      leds1[i].setRGB(255, 0, 0);// Rouge si led entre 1 et 5
    }
    if (i >= 5 && i < 10) {
      leds1[i].setRGB(255, 255, 0); //Jaune si led entre 5 et 10
    }
    if (i >= 10 && i < 30) {
      leds1[i].setRGB(0, 255, 0);// vert si led entre 10 et 30
    }
    if (i >= 30 && i < 35) {
      leds1[i].setRGB(255, 255, 0);// Jaune si led entre 30 et 35
    }
    if (i > 34) {
      leds1[i].setRGB(255, 0, 0); //Rouge si led entre 35 et 40
       }  
    FastLED.show();
    if (redpush == 1) {
      ledposition = i;
      i = -1;
      gamestate = 3;
      exchange+=exchangeON;
      redpush = 0;
    }
    pause();
    if (i == 0) {
      greenwin = 1;
      float exchange = 0;
      gamestate = 4;
    }
  }
}

void showscore() {
  leds2off();
  leds3off();
  switch (redscore) {
   
    case 1:
      for (i = 0; i < sizeof(N1); i++) {
        leds2[N1[i]].setRGB(0, 0, 200);// Couleur du score du joueur 1
      }
      break;
    case 2:
      for (i = 0; i < sizeof(N2); i++) {
        leds2[N2[i]].setRGB(0, 0, 200);// Couleur du score du joueur 1
      }
      break;
    case 3:
      for (i = 0; i < sizeof(N3); i++) {
        leds2[N3[i]].setRGB(0, 0, 200);// Couleur du score du joueur 1
      }
      break;
    case 4:
      for (i = 0; i < sizeof(N4); i++) {
        leds2[N4[i]].setRGB(0, 0, 200);// Couleur du score du joueur 1
      }
      break;
    /*case 5:
      for (i = 0; i < sizeof(N5); i++) {
        leds2[N5[i]].setRGB(0, 0, 200);// Couleur du score du joueur 1
      }
    break;*/
    
  }
  switch (greenscore) {
   
    case 1:
      for (i = 0; i < sizeof(N1); i++) {
        leds3[N1[i]].setRGB(255, 0, 255);// Couleur du score du joueur 2
      }
      break;
    case 2:
      for (i = 0; i < sizeof(N2); i++) {
        leds3[N2[i]].setRGB(255, 0, 255);// Couleur du score du joueur 2
      }
      break;
    case 3:
      for (i = 0; i < sizeof(N3); i++) {
        leds3[N3[i]].setRGB(255, 0, 255);// Couleur du score du joueur 2
      }
      break;
    case 4:
      for (i = 0; i < sizeof(N4); i++) {
        leds3[N4[i]].setRGB(255, 0, 255);// Couleur du score du joueur 2
      }
      break;
    /*case 5:
      for (i = 0; i < sizeof(N5); i++) {
        leds3[N5[i]].setRGB(255, 0, 255);// Couleur du score du joueur 1
      }
    break;*/
    
  }
  FastLED.show();
}

void redwinanimation() {
  leds1off();
  leds2off();
  leds3off();
  for (i = 0; i < 4; i++) {
    for (m = 0; m < NUM_LEDS2; m++) {
      leds2[m].setRGB(0, 255, 0);
    }
    for (m = 0; m < NUM_LEDS3; m++) {
      leds3[m].setRGB(255, 0, 0);
    }
    FastLED.show();
    delay(500);
    for (m = 0; m < NUM_LEDS2; m++) {
      leds2[m].setRGB(0, 0, 0);
    }
    for (m = 0; m < NUM_LEDS3; m++) {
      leds3[m].setRGB(0, 0, 0);
    }
    FastLED.show();
    delay(500);
  }
}

void greenwinanimation() {
  leds1off();
  leds2off();
  leds3off();
  for (i = 0; i < 4; i++) {
    for (m = 0; m < NUM_LEDS3; m++) {
      leds3[m].setRGB(0, 255, 0);
    }
    for (m = 0; m < NUM_LEDS2; m++) {
      leds2[m].setRGB(255, 0, 0);
    }
    FastLED.show();
    delay(500);
    for (m = 0; m < NUM_LEDS2; m++) {
      leds3[m].setRGB(0, 0, 0);
    }
    for (m = 0; m < NUM_LEDS3; m++) {
      leds2[m].setRGB(0, 0, 0);
    }
    FastLED.show();
    delay(500);
  }
}

void leds2off() {
  for (m = 0; m < NUM_LEDS2; m++) {
    leds2[m].setRGB(0, 0, 0);
  }
}

void leds3off() {
  for (m = 0; m < NUM_LEDS3; m++) {
    leds3[m].setRGB(0, 0, 0);
  }
}

void leds1off() {
  for (m = 0; m < NUM_LEDS1; m++) {
    leds1[m].setRGB(0, 0, 0);
  }
}

void pause() {
  starttime = millis();
  currenttime = millis();
  while (currenttime - starttime <= waittime) {
    currenttime = millis();
  }
}
