//Define pins for buttons and leds
#define buttonC1 D5
#define buttonC2 D10
#define buttonC3 D9
#define buttonC4 D8

#define ledC1 D0
#define ledC2 D2
#define ledC3 D3
#define ledC4 D4

// Arrays for buttons and leds
const int arr_Buttons[] = {buttonC1, buttonC2, buttonC3, buttonC4};
const int arr_Leds[] = {ledC1, ledC2, ledC3, ledC4};

//Flags for losing
bool b_Lose = false;
bool b_Correct = false;

//Array of levels and max number of levels
int arr_Levels[4];
const int maxLevels = 4;

//Delays
float delayT = 550;
float delayP = 250;

void setup() {
  Serial.begin(9600);
  int x;
  //Set modes for leds and buttons by iterating the arrays
  for (int i = 0; i < 4; i++) {
    pinMode(arr_Buttons[i], INPUT);
    pinMode(arr_Leds[i], OUTPUT);
  }
  //Wait for the button to be pressed
  while(!digitalRead(D5)){
    x=micros();
    randomSeed(micros());
  }
 /* while(1){
    x = random(0, 4);
    Serial.println(x);
    delay(1000);

  }*/
}
//New level with random number between 0-3
int newLevel() {
    int x = random(0, 4); 
    Serial.print(x); 
    return x;  
}
//Control an specific led
void controlLed(int index, bool value) {
  digitalWrite(arr_Leds[index], value);  // Turn on the selected LED
}
//Leds ON
void ledsON() {
  for (int i = 0; i < 4; i++) {
    digitalWrite(arr_Leds[i], HIGH);
  }
}
//Leds Off
void ledsOFF() {
  for (int i = 0; i < 4; i++) {
    digitalWrite(arr_Leds[i], LOW);
  }
}
//Blink all leds
void blinkLeds(int times) {
  for (int i = 0; i < times; i++) {
    ledsON();
    delay(delayP);
    ledsOFF();
    delay(delayP);
  }
}
//For next level blink 1 time
void nextLevel() {
  blinkLeds(1);
}
//Sequence of win
void Win() {
  for (int i = 0; i < 4; i++) {
    digitalWrite(arr_Leds[i], HIGH);
    delay(1000);
  }
  blinkLeds(3);
}
//Sequence of lose
void Lose() {
  for (int i = 0; i < 4; i++) {
    digitalWrite(arr_Leds[i], HIGH);
  }
  delay(1000);
  for (int i = 0; i < 4; i++) {
    digitalWrite(arr_Leds[i], LOW);
    delay(1000);
  }
}

//All the game
void loop() {
  int k = 0; //Variable for checking level
  while (!b_Lose && k < maxLevels) { //Continue while not losing
    arr_Levels[k] = newLevel(); //New level
    nextLevel(); //Sequence of next level
    for (int i=0; i<maxLevels; i++){ //Some printing on the serial monnitor
      Serial.print("I: ");
      Serial.print(i);
      Serial.print("Value: ");
      Serial.print(arr_Levels[i]);
      Serial.print(" | ");
    }
    Serial.println();

    for (int i = 0; i < (k+1); i++) { //Sequence of leds on the level
      controlLed(arr_Levels[i], true);
      delay(delayT);

      controlLed(arr_Levels[i], false);
      delay(delayT);
    }

    for (int i = 0; i < (k+1); i++) { //Check buttons
      int j = 0;
      b_Correct = false;

      while (!b_Correct && !b_Lose) {
        while (digitalRead(arr_Buttons[j])) {
          digitalWrite(arr_Leds[j], HIGH); //Led of the button on
          if (j != arr_Levels[i]) { //Ckeck if the button corresponds to the led
            b_Lose = true;
          } else {
            b_Correct = true;
          }
        }

        digitalWrite(arr_Leds[j], LOW); //Led of the button off

        if (j < maxLevels - 1) { //Iterait the buttons
          j += 1;
        } else {
          j = 0;
        }
      }

      if (b_Lose) {
        break;
      }
    }

    delayT -= 50; //Decrease the delay
    k ++;
  }

  if (b_Lose) { //Lose
    Lose();
  } else { //Win
    Win();
  }
  //Reset variables
  delayT = 500;
  b_Lose = false;
  delay(1500);
}