#define NUM_LEDS 8
#define NUM_BOTONES 3

// *** PINES ACTUALIZADOS PARA WOKWI ***
const int botones[NUM_BOTONES] = {13, 12, 14};  // Botones (Bit 0, 1, 2)
const int leds[NUM_LEDS] = {25, 26, 27, 32, 33, 15, 4, 2};  // LEDs 1-8 (pines válidos en Wokwi)

// Variables
int modoActual = 0;
unsigned long milisegundosAnteriores = 0;
int estadoLed = 0;
int contador = 0;
int fib1 = 0, fib2 = 1;
int numeroCollatz = 16;  // Número inicial interesante para Collatz
int posicion = 0;
bool direccionDerecha = true;

void setup() {
  Serial.begin(115200);
  
  // Inicializar LEDs
  for (int i = 0; i < NUM_LEDS; i++) {
    pinMode(leds[i], OUTPUT);
    digitalWrite(leds[i], LOW);  // Apagar todos al inicio
  }
  
  // Inicializar botones con pull-down interno
  for (int i = 0; i < NUM_BOTONES; i++) {
    pinMode(botones[i], INPUT_PULLDOWN);
  }
  
  Serial.println("Sistema iniciado. Listo para usar.");
}

void loop() {
  // *** LECTURA DE BOTONES CON ANTI-REBOTE (DEBOUNCE) ***
  static unsigned long ultimoCambio = 0;
  static int ultimoModo = modoActual;
  
  if (millis() - ultimoCambio > 200) {  // Esperar 200ms para evitar rebotes
    int nuevoModo = 0;
    for (int i = 0; i < NUM_BOTONES; i++) {
      nuevoModo += digitalRead(botones[i]) << i;  // Leer en binario (0-7)
    }
    
    if (nuevoModo != ultimoModo) {
      ultimoModo = nuevoModo;
      ultimoCambio = millis();
    }
    
    if (nuevoModo != modoActual) {
      modoActual = nuevoModo;
      reiniciarModo();
      Serial.print("Modo cambiado a: ");
      Serial.println(modoActual);
    }
  }
  
  // *** EJECUTAR MODO ACTUAL ***
  switch (modoActual) {
    case 0: apagarTodosLosLeds(); break;       // Modo 0: Apagar todo
    case 1: lucesNavidenas(); break;           // Modo 1: Luces navideñas
    case 2: ojoDeKit(); break;                 // Modo 2: Ojo de Kit
    case 3: corrimiento(); break;              // Modo 3: Desplazamiento
    case 4: contadorBinario(); break;          // Modo 4: Contador binario
    case 5: fibonacci(); break;                // Modo 5: Fibonacci
    case 6: collatz(); break;                  // Modo 6: Conjetura de Collatz
    case 7: sorpresa(); break;                 // Modo 7: Sorpresa
    default: apagarTodosLosLeds(); break;      // Por defecto, apagar
  }
}

// ==============================================
// ** FUNCIONES AUXILIARES **
// ==============================================

void reiniciarModo() {
  apagarTodosLosLeds();
  milisegundosAnteriores = millis();
  estadoLed = 0;
  contador = 0;
  fib1 = 0;
  fib2 = 1;
  numeroCollatz = 16;  // Reiniciar Collatz con número interesante
  posicion = 0;
  direccionDerecha = true;
  Serial.println("Modo reiniciado.");
}

void apagarTodosLosLeds() {
  for (int i = 0; i < NUM_LEDS; i++) {
    digitalWrite(leds[i], LOW);
  }
}

void establecerLedsDesdeBinario(int valor) {
  for (int i = 0; i < NUM_LEDS; i++) {
    digitalWrite(leds[i], (valor >> i) & 1);  // Encender según bits
  }
}

// ==============================================
// ** EFECTOS DE LEDS **
// ==============================================

// Modo 1: Luces navideñas (alterna pares/impares)
void lucesNavidenas() {
  if (millis() - milisegundosAnteriores >= 500) {
    milisegundosAnteriores = millis();
    estadoLed = !estadoLed;
    
    for (int i = 0; i < NUM_LEDS; i++) {
      digitalWrite(leds[i], (i % 2 == 0) ? estadoLed : !estadoLed);
    }
  }
}

// Modo 2: Ojo de Kit (expansión/contracción)
void ojoDeKit() {
  if (millis() - milisegundosAnteriores >= 300) {
    milisegundosAnteriores = millis();
    
    apagarTodosLosLeds();
    
    if (direccionDerecha) {
      digitalWrite(leds[3 + posicion], HIGH);
      digitalWrite(leds[4 - posicion], HIGH);
      posicion++;
      if (posicion > 3) direccionDerecha = false;
    } else {
      posicion--;
      digitalWrite(leds[3 + posicion], HIGH);
      digitalWrite(leds[4 - posicion], HIGH);
      if (posicion <= 0) direccionDerecha = true;
    }
  }
}

// Modo 3: Corrimiento (LED que se desplaza)
void corrimiento() {
  if (millis() - milisegundosAnteriores >= 200) {
    milisegundosAnteriores = millis();
    
    apagarTodosLosLeds();
    digitalWrite(leds[posicion], HIGH);
    
    posicion = (posicion + 1) % NUM_LEDS;  // Circular
  }
}

// Modo 4: Contador binario (0-255)
void contadorBinario() {
  if (millis() - milisegundosAnteriores >= 1000) {
    milisegundosAnteriores = millis();
    establecerLedsDesdeBinario(contador);
    contador = (contador + 1) % 256;  // Reiniciar en 255
  }
}

// Modo 5: Secuencia de Fibonacci
void fibonacci() {
  if (millis() - milisegundosAnteriores >= 1000) {
    milisegundosAnteriores = millis();
    
    int siguiente = fib1 + fib2;
    fib1 = fib2;
    fib2 = (siguiente > 255) ? 1 : siguiente;  // Reiniciar si excede 255
    
    establecerLedsDesdeBinario(fib1);
  }
}

// Modo 6: Conjetura de Collatz
void collatz() {
  if (millis() - milisegundosAnteriores >= 1000) {
    milisegundosAnteriores = millis();
    
    establecerLedsDesdeBinario(numeroCollatz);
    
    numeroCollatz = (numeroCollatz % 2 == 0) ? 
      numeroCollatz / 2 : 
      numeroCollatz * 3 + 1;
    
    if (numeroCollatz > 255 || numeroCollatz == 1) {
      numeroCollatz = random(1, 50);  // Nuevo número aleatorio
    }
  }
}

// Modo 7: Efecto sorpresa (barrido progresivo)
void sorpresa() {
  if (millis() - milisegundosAnteriores >= 150) {
    milisegundosAnteriores = millis();
    
    apagarTodosLosLeds();
    for (int i = 0; i <= estadoLed && i < NUM_LEDS; i++) {
      digitalWrite(leds[i], HIGH);
    }
    
    estadoLed = (estadoLed + 1) % (NUM_LEDS * 2 + 1);
  }
}