#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"

// Configuração do teclado e display
#define LINHAS 4
#define COLUNAS 4
#define DIGITOS 4

const uint8_t linhas_pins[LINHAS] = {28, 27, 26, 22};
const uint8_t colunas_pins[COLUNAS] = {21, 20, 19, 18};
const uint8_t digitos_pins[DIGITOS] = {10, 11, 12, 13};
const uint8_t segmentos_pins[8] = {2, 3, 4, 5, 6, 7, 8, 9};

// LEDs e buzzer
const uint8_t led_verde = 16;
const uint8_t led_vermelho = 17;
const uint8_t buzzer = 15;

const char teclado[LINHAS][COLUNAS] = {
    {'1', '2', '3', 'A'},
    {'4', '5', '6', 'B'},
    {'7', '8', '9', 'C'},
    {'*', '0', '#', 'D'}
};

// Variáveis globais
char senha_digitada[DIGITOS] = {' ', ' ', ' ', ' '};
int indice_senha = 0;
uint32_t ultima_leitura = 0;  // Para debounce
const uint32_t debounce_delay = 200;  // 200ms de debounce

// Mapeamento de segmentos para dígitos de 0 a 9
const uint8_t segmentos_valores[10] = {
    0b00111111, // 0
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111  // 9
};

// Funções auxiliares
void teclado_init() {
    for (int i = 0; i < LINHAS; i++) {
        gpio_init(linhas_pins[i]);
        gpio_set_dir(linhas_pins[i], GPIO_OUT);
        gpio_put(linhas_pins[i], 0);
    }
    for (int i = 0; i < COLUNAS; i++) {
        gpio_init(colunas_pins[i]);
        gpio_set_dir(colunas_pins[i], GPIO_IN);
        gpio_pull_down(colunas_pins[i]);
    }
}

void display_init() {
    for (int i = 0; i < DIGITOS; i++) {
        gpio_init(digitos_pins[i]);
        gpio_set_dir(digitos_pins[i], GPIO_OUT);
        gpio_put(digitos_pins[i], 0);
    }
    for (int i = 0; i < 8; i++) {
        gpio_init(segmentos_pins[i]);
        gpio_set_dir(segmentos_pins[i], GPIO_OUT);
        gpio_put(segmentos_pins[i], 0);
    }
}

void leds_buzzer_init() {
    gpio_init(led_verde);
    gpio_set_dir(led_verde, GPIO_OUT);
    gpio_put(led_verde, 0);

    gpio_init(led_vermelho);
    gpio_set_dir(led_vermelho, GPIO_OUT);
    gpio_put(led_vermelho, 0);

    gpio_init(buzzer);
    gpio_set_dir(buzzer, GPIO_OUT);
    gpio_put(buzzer, 0);
}

void display_atualizar(int digito, char valor) {
    if (valor < '0' || valor > '9') {
        // Se for um caractere inválido, limpa o display
        for (int i = 0; i < 8; i++) {
            gpio_put(segmentos_pins[i], 0);
        }
    } else {
        uint8_t segmentos = segmentos_valores[valor - '0'];
        for (int i = 0; i < 8; i++) {
            gpio_put(segmentos_pins[i], (segmentos >> i) & 1);
        }
    }

    for (int i = 0; i < DIGITOS; i++) {
        gpio_put(digitos_pins[i], i == digito);
    }
}

void display_exibir_senha() {
    for (int i = 0; i < DIGITOS; i++) {
        display_atualizar(i, senha_digitada[i]);
        sleep_ms(5);  // Multiplexação
    }
}

char ler_teclado() {
    uint32_t agora = to_ms_since_boot(get_absolute_time());
    if (agora - ultima_leitura < debounce_delay) {
        return '\0';  // Ignora leituras dentro do intervalo de debounce
    }

    for (int linha = 0; linha < LINHAS; linha++) {
        gpio_put(linhas_pins[linha], 1);
        for (int coluna = 0; coluna < COLUNAS; coluna++) {
            if (gpio_get(colunas_pins[coluna])) {
                gpio_put(linhas_pins[linha], 0);
                ultima_leitura = agora;  // Atualiza o tempo da última leitura
                return teclado[linha][coluna];
            }
        }
        gpio_put(linhas_pins[linha], 0);
    }
    return '\0';
}

void acionar_leds_buzzer(char tecla) {
    if (tecla == 'A') {
        gpio_put(led_verde, 1);
        sleep_ms(200);
        gpio_put(led_verde, 0);
    } else if (tecla == 'B') {
        gpio_put(led_vermelho, 1);
        sleep_ms(200);
        gpio_put(led_vermelho, 0);
    } else if (tecla == 'C') {
        gpio_put(buzzer, 1);
        sleep_ms(200);
        gpio_put(buzzer, 0);
    }
}

// Programa principal
int main() {
    stdio_init_all();
    teclado_init();
    display_init();
    leds_buzzer_init();

    while (true) {
        char tecla = ler_teclado();
        if (tecla != '\0') {
            printf("Tecla pressionada: %c\n", tecla);

            // Aciona LEDs e buzzer
            acionar_leds_buzzer(tecla);

            // Atualiza senha digitada
            if (tecla >= '0' && tecla <= '9') {
                senha_digitada[indice_senha++] = tecla;
                if (indice_senha == DIGITOS) {
                    indice_senha = 0;  // Reinicia a senha após 4 dígitos
                }
            }
        }
        display_exibir_senha();
    }

    return 0;
}