#include <stdio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
#include <wiegand.h>
#include <esp_log.h>
#include <string.h>
#include <evse_api.h>
#include <ocpp.h>

static const char *TAG = "Wiegand_reader";

#define WIEGAND_PIN_D0 19
#define WIEGAND_PIN_D1 18
#define WIEGAND_BUF_SIZE 50
#define QUEUE_SIZE 10

static wiegand_reader_t reader;
static QueueHandle_t data_queue = NULL;

// Single data packet
typedef struct
{
    uint8_t data[WIEGAND_BUF_SIZE];
    size_t bits;
} data_packet_t;

// callback on new data in reader
static void reader_callback(wiegand_reader_t *r)
{
    data_packet_t p;
    p.bits = r->bits;
    size_t data_size = (r->bits + 7) / 8;
    memcpy(p.data, r->buf, data_size);

    if (xQueueSendToBack(data_queue, &p, portMAX_DELAY) != pdTRUE) {
        ESP_LOGE(TAG, "Failed to send data to queue");
    }
}

static void wiegand_task(void *arg)
{
    // Create queue
    data_queue = xQueueCreate(QUEUE_SIZE, sizeof(data_packet_t));
    if (!data_queue)
    {
        ESP_LOGE(TAG, "Error creating queue");
        ESP_ERROR_CHECK(ESP_ERR_NO_MEM);
    }

    // Initialize reader
    esp_err_t err = wiegand_reader_init(&reader, WIEGAND_PIN_D0, WIEGAND_PIN_D1,
                                        true, WIEGAND_BUF_SIZE, reader_callback, 
                                        WIEGAND_MSB_FIRST, WIEGAND_LSB_FIRST);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize Wiegand reader: %s", esp_err_to_name(err));
        return;
    }

    data_packet_t p;
    while (1)
    {
        ESP_LOGI(TAG, "Waiting for Wiegand data...");
        if (xQueueReceive(data_queue, &p, pdMS_TO_TICKS(1000)) != pdTRUE) {
            ESP_LOGW(TAG, "No Wiegand data received within the timeout");
            continue;
        }

        ESP_LOGI(TAG, "Bits received: %d", p.bits);
        for (size_t i = 0; i < (p.bits + 7) / 8; i++)
            ESP_LOGI(TAG, " 0x%02x", p.data[i]);

        char str[20];
        if (p.bits == 26 || p.bits == 34)
        {
            evse_authorize();

            
            
            /*----26
            sprintf(str, "%03d%03d%03d", p.data[0], p.data[1], p.data[2]);

            if (ocpp_is_TransactionActive())
            {
                ocpp_end_transaction(str);
            }
            else
            {
                ocpp_begin_transaction(str);
            }*/
            /*----34
            sprintf(str, "%03d%03d%03d%03d", p.data[0], p.data[1], p.data[2], p.data[3]);

            if (ocpp_is_TransactionActive())
            {
                ocpp_end_transaction(str);
            }
            else
            {
                ocpp_begin_transaction(str);
            }
            */

        }
    }
}

void initialize_wiegand_reader()
{
    ESP_LOGI(TAG, "Starting Wiegand reader");
    xTaskCreate(wiegand_task, TAG, configMINIMAL_STACK_SIZE * 4, NULL, 5, NULL);
}
