#include <Adafruit_NeoPixel.h>
#include <Button.h>

// Estrutura para armazenar o estado de cada botão
struct ButtonState {
  bool state;
  unsigned long lastMillis;
  unsigned long buttonPressedTime;
  unsigned long interval;
};

// Inicialização dos estados dos botões
ButtonState button0 = {false, 0, 0, 200};
ButtonState button1 = {false, 0, 0, 200};
ButtonState button2 = {false, 0, 0, 200};
ButtonState button3 = {false, 0, 0, 200};



// C++ code
//

/*LED RGG*/
#define LED_DATA_IN 3
#define LED_RBG_QTD 16

/*COnfiguração 4 LEDS*/
const int BOTAO_0_G = 9;
const int BOTAO_1_B = 6;
const int BOTAO_2_R = 4;
const int BOTAO_3_Y = 7;

#define START_BUTTON 2

//Pino Buzzer
#define BUZZER 10

int SystemState = 0;

//Variavel para analisar o valor randomico da cor gerada
long randomColor; 

//Variavel para armazenar o tempo contado
volatile unsigned long timerCount = 0;
// Define os períodos dos timers em milissegundos
#define TIMER_PERIOD_1_SECOND 1

//Vetores para armazenar os valores dos Leds e dos Botões
int ledPastValues[] = {0};
int len;

int corretAnswers = 0;
volatile bool userTurn = false;
int currentStep = 0;
int userStep = 0;
int index = 0;

int buttonReadValue = -1;
int buttonRead0 = 0;
int buttonRead1 = 0;
int buttonRead2 = 0;
int buttonRead3 = 0;

Adafruit_NeoPixel RGB(LED_RBG_QTD, LED_DATA_IN, NEO_RBG + NEO_KHZ800);


void setup() {

  //Configura timer para operacao normal
  TCCR1A = 0;
  //limpa registrador
  TCCR1B = 0;
  //zera temporizado
  TCNT1  = 0;                
  //Valor da comparacao em Hexa para tempo de um segundo
  OCR1A = 0x3D09;

  //Habilita modo comparação e configura preescaler como 1024
  TCCR1B |= (1 << WGM12) | (1<<CS10) | (1<<CS12); 
  //Permite interrupções
  TIMSK1 |= (1 << OCIE1A);  // habilita interrupção por igualdade de comparação

  //Habilita o Botao de iniciar/ desligar
  pinMode(START_BUTTON, INPUT);

  pinMode(BOTAO_0_G, INPUT_PULLUP);
  pinMode(BOTAO_1_B, INPUT_PULLUP);
  pinMode(BOTAO_2_R, INPUT_PULLUP);
  pinMode(BOTAO_3_Y, INPUT_PULLUP);


  //Define como OUTPUT o pino de saida para o LED RBG
  pinMode(LED_DATA_IN, OUTPUT);

  //Inicializa RGB
  RGB.begin();
  RGB.show();
  attachInterrupt(digitalPinToInterrupt(START_BUTTON), ButtonInterrupt, RISING);

  Serial.begin(9600);
  Serial.println("Start");


}


void loop()
{
  if(SystemState == 1){

    buttonRead0 = checkButton(BOTAO_0_G, button0);
    buttonRead1 = checkButton(BOTAO_1_B, button1);
    buttonRead2 = checkButton(BOTAO_2_R, button2);
    buttonRead3 = checkButton(BOTAO_3_Y, button3);
    
    if(buttonRead0 == 1){
      buttonReadValue = 0;
        Serial.print("Buton Value: ");
        Serial.println(buttonReadValue);
    }
    if(buttonRead1 == 1){
      buttonReadValue = 1;
        Serial.print("Buton Value: ");
        Serial.println(buttonReadValue);
    }
    if(buttonRead2 == 1){
      buttonReadValue = 2;
        Serial.print("Buton Value: ");
        Serial.println(buttonReadValue);
    }
    if(buttonRead3 == 1){
      buttonReadValue = 3;
        Serial.print("Buton Value: ");
        Serial.println(buttonReadValue);
    }
    else {
    buttonReadValue = -1;
  }
    

    if(userTurn == true && buttonReadValue!= -1){
      Serial.println("Rodada Jogador");
      if(ledPastValues[userStep] == buttonReadValue){
           Serial.println("Acertou");
        userStep++;
        Serial.print("Current Step: ");
        Serial.println(currentStep);
        Serial.print("User SteP: ");
        Serial.println(userStep);
        if(userStep > currentStep){
             Serial.println("Passou");

          currentStep++;
          userStep = 0;
          userTurn = false;
          Serial.print("Current Step: ");

          Serial.println(currentStep);
        }
      }
      else if(ledPastValues[userStep] != buttonReadValue){
        Serial.println("Perdeu");
    }

  }

  
}
}

ISR(TIMER1_COMPA_vect){
  clearColor();
  timerCount++;
    if(SystemState == 1){
      if(userTurn == false){
        randomSeed(analogRead(0));
        randomColor = random(0,4);
        ledPastValues[currentStep] = randomColor;
        if(index <= currentStep){
          Serial.print("Color: ");
          Serial.println(randomColor);
          choosingColor(ledPastValues[currentStep]);

        }
        else if (index > currentStep){
          userTurn = true;
          index = 0;
        }
        
        }

        /*
        else{
             Serial.println("Hora Jogador");
          index = 0;
          userTurn = true;
        }         
        */
      }
      
      
        else{
      clearColor();
    }
}

void setColor(int index, int r, int g, int b){
  RGB.setPixelColor((index%4)*4, r, g, b);
  RGB.setPixelColor((index%4)*4+1,r, g, b);
  RGB.setPixelColor((index%4)*4+2, r, g, b);
  RGB.setPixelColor((index%4)*4+3, r, g, b);
  RGB.show();
}

void choosingColor(int randomNumber){
  
  switch (randomNumber){
    case 0:
      setColor(0, 255, 0, 0); //Verde
      break; 
    case 1:
      setColor(1, 0, 255, 0); //Azul
      break; 
    case 2:
      setColor(2, 0, 0, 255); //Vermelho
      break;
    case 3:
      setColor(3, 255, 0, 255); //Amarelo
      break;
  }
}

void clearColor(){
  setColor(0, 0, 0, 0);
  setColor(1, 0, 0, 0);
  setColor(2, 0, 0, 0);
  setColor(3, 0, 0, 0);
}

  

void ButtonInterrupt(){
    SystemState = !SystemState;
    if(SystemState == true){
      Serial.println("inicia Genius");
      currentStep = 0;
      userStep = 0;
    }
    else{
      Serial.println("Desliga Genius");
      clearColor();
    }
  }


int checkButton(int buttPin, ButtonState &buttonState) {
  unsigned long currentMillis = millis();
  int reading = digitalRead(buttPin);

  if (reading == HIGH && buttonState.state) {
    // O botão foi solto
    buttonState.state = false;
    buttonState.interval = 200;  // Reseta o intervalo para 200ms
  }

  if (reading == LOW) {
    // O botão foi pressionado
    buttonState.state = true;
    buttonState.buttonPressedTime = currentMillis;
  }

  if (buttonState.state) {
    if (currentMillis - buttonState.buttonPressedTime >= 1000) {
      // O botão está pressionado há 1 segundo, diminui o intervalo pela metade
      buttonState.interval /= 2;
      buttonState.buttonPressedTime = currentMillis;
    }

    if (currentMillis - buttonState.lastMillis >= buttonState.interval) {
      // Incrementa o contador a cada 'intervalo' milissegundos
      //counter++;
      buttonState.lastMillis = currentMillis;
      //Serial.print("Counter: ");
      //Serial.println(counter);
      //Serial.println("RED");
      return 1;  // Retorna 1 indicando que o botão foi acionado
    }
  }

  return 0;  // Retorna 0 indicando que o botão não foi acionado
}

void showSequence() {
  for (int i = 0; i <= currentStep; i++) {
    choosingColor(ledPastValues[i]);
    delay(500);
    clearColor();
    delay(250);
  }
}
$abcdeabcde151015202530fghijfghij
$abcdeabcde151015202530fghijfghij
4-Digit Display