const int PinVermelhoCarros = 2;
const int PinAmareloCarros = 0;
const int PinVerdeCarros = 4;
const int PinVermelhoPedestre = 14;
const int PinVerdePedestre = 12;
const int botao = 19;
const int buzzer = 15;
const int sensor = 13; // Pino do sensor de ultrapassagem de sinal vermelho
const int pinAzulMultas = 16; // Pino para contar as multas

// Variáveis globais para controlar o estado do semáforo e do pedestre
int estadoAtual = 0; // Começa com estado 0 (verde)
unsigned long tempoInicio; // Variável para armazenar o tempo de início de cada etapa
bool sinalAberto = false; // Variável para rastrear se o sinal está aberto
bool botaoPressionado = false; // Variável para rastrear se o botão foi pressionado
int somAtual = 0; // Variável para controlar o som atual no buzzer

void setup() {
  // Configuração dos pinos
  pinMode(PinVermelhoCarros, OUTPUT);
  pinMode(PinAmareloCarros, OUTPUT);
  pinMode(PinVerdeCarros, OUTPUT);
  pinMode(PinVermelhoPedestre, OUTPUT);
  pinMode(PinVerdePedestre, OUTPUT);
  pinMode(botao, INPUT);
  pinMode(buzzer, OUTPUT);
  pinMode(sensor, INPUT);
  pinMode(pinAzulMultas, OUTPUT);

  // Inicialmente, todos os sinais devem estar desligados
  digitalWrite(PinVermelhoCarros, LOW);
  digitalWrite(PinAmareloCarros, LOW);
  digitalWrite(PinVerdeCarros, LOW);
  digitalWrite(PinVermelhoPedestre, LOW);
  digitalWrite(PinVerdePedestre, LOW);
}

void loop() {
  int estadoBotao = digitalRead(botao);
  int estadoSensor = digitalRead(sensor);

  // Chamada da função para controlar o estado do semáforo e do pedestre
  mudarEstado(estadoAtual);

  // Etapa 1: Sinal verde para carros, vermelho para pedestres
  if (!sinalAberto) {
    if (!botaoPressionado && estadoBotao == HIGH) {
      emitirSom(1); // Emitir som para sinal verde
      botaoPressionado = true;
      tempoInicio = millis(); // Armazena o tempo atual
    }

    if (millis() - tempoInicio >= 10000) {
      digitalWrite(PinVermelhoCarros, HIGH);
      digitalWrite(PinVermelhoPedestre, HIGH);
      sinalAberto = true;
      tempoInicio = millis(); // Reinicia o tempo de início para a próxima etapa
    } else {
      digitalWrite(PinVerdeCarros, HIGH);
      digitalWrite(PinVermelhoPedestre, HIGH);
    }
  }

  // Etapa 2: Sinal amarelo
  if (sinalAberto && millis() - tempoInicio >= 5000 && millis() - tempoInicio <= 8000) {
    digitalWrite(PinVerdeCarros, LOW);
    digitalWrite(PinVermelhoCarros, LOW);
    digitalWrite(PinAmareloCarros, HIGH);
  }

  // Etapa 3: Sinal vermelho para carros, verde para pedestres
  if (sinalAberto && millis() - tempoInicio >= 8000 && millis() - tempoInicio <= 17000) {
    digitalWrite(PinAmareloCarros, LOW);
    digitalWrite(PinVermelhoCarros, HIGH);
    digitalWrite(PinVerdePedestre, HIGH);
    if (botaoPressionado && estadoBotao == HIGH && somAtual == 1) {
      emitirSom(2); // Emitir som diferente para sinal vermelho
      botaoPressionado = false; // Reiniciar variável de controle do botão
    }
    // Chamada da função para detectar infração
    Multas();
  }

  // Verificação de ultrapassagem do sinal vermelho
  if (sinalAberto && millis() - tempoInicio >= 8000 && millis() - tempoInicio <= 17000 && estadoSensor == HIGH) {
    digitalWrite(pinAzulMultas, HIGH); // Ativa o pino de multas
    Serial.println("Carro multado!"); // Imprime no terminal indicando que um carro foi multado
    digitalWrite(pinAzulMultas, LOW);
  }

  // Se o botão foi pressionado e o estado atual é alto
  if (botaoPressionado && estadoBotao == HIGH) {
    // Emitir som para indicar que o botão foi pressionado
    emitirSomBotao();
  }
}

void mudarEstado(int estado) {
  switch (estado) {
    case 0:  // Verde
      digitalWrite(PinVerdeCarros, HIGH);
      digitalWrite(PinAmareloCarros, LOW);
      digitalWrite(PinVermelhoCarros, LOW);
      digitalWrite(PinVermelhoPedestre, HIGH);
      digitalWrite(PinVerdePedestre, LOW);
      tempoInicio = millis();
      break;
    case 1:  // Amarelo
      digitalWrite(PinVerdeCarros, LOW);
      digitalWrite(PinAmareloCarros, HIGH);
      digitalWrite(PinVermelhoCarros, LOW);
      digitalWrite(PinVermelhoPedestre, LOW);
      digitalWrite(PinVerdePedestre, LOW);
      tempoInicio = millis();
      break;
    case 2:  // Vermelho
      digitalWrite(PinVerdeCarros, LOW);
      digitalWrite(PinAmareloCarros, LOW);
      digitalWrite(PinVermelhoCarros, HIGH);
      digitalWrite(PinVermelhoPedestre, LOW);
      digitalWrite(PinVerdePedestre, HIGH);
      tempoInicio = millis();
      // tempoRestanteVermelho = tempoVermelho; // Reinicia o tempo restante (comentei isso porque essa variável não está declarada)
      break;
  }

  // Avança para o próximo estado (cíclico)
  estadoAtual = (estadoAtual + 1) % 3;
}

void emitirSom(int tipoSom) {
  if (tipoSom == 1 && somAtual != 1) {
    tone(buzzer, 1000); // Emitir som para sinal verde
    somAtual = 1;
  } else if (tipoSom == 2 && somAtual != 2) {
    tone(buzzer, 2000); // Emitir som para sinal vermelho
    somAtual = 2;
  }
}

void emitirSomBotao() {
  tone(buzzer, 1000); // Emitir som para indicar que o botão foi pressionado
  delay(2000); // Manter o som por 2 segundos
  noTone(buzzer); // Desligar o som do buzzer
}