#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"

#include "mcp2521_hardware_esp_bus.hpp"
#include "mcp2521_hardware_esp.hpp"

MCP2521_HardwareHandle_ESPBus::MCP2521_HardwareHandle_ESPBus(
        QueueHandle_t send_queue,
        spi_host_device_t spi_host,
        spi_bus_config_t * bus_config,
        gpio_num_t cs, 
        gpio_num_t int_pin
) : MCP2521_HardwareHandle_ESP(spi_host, bus_config, cs, int_pin) {
    this->send_queue = send_queue;
    this->receive_queue = xQueueCreate(3, sizeof(spi_message_t));
}

void MCP2521_HardwareHandle_ESPBus::spi_transmit(spi_transaction_t *t) {
    spi_message_t message = {
        .transaction = t,
        .queue = send_queue,
        .spi_device_handle = spi_device_handle
    };

    xQueueSend(send_queue, &message, portMAX_DELAY);
    xQueueReceive(receive_queue, &message, portMAX_DELAY);
}

void MCP2521_HardwareHandle_ESPBus::initPins(
    gpio_num_t int_pin
) {
    canInterruptSemaphore = xSemaphoreCreateBinary();

    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_NEGEDGE;
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = 1 << int_pin;
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
    gpio_config(&io_conf);

    gpio_isr_handler_add(int_pin, gpio_isr_can_handler, this);

    char taskName[32];
    sprintf(taskName, "canInterruptTask_%d", int_pin);

    xTaskCreatePinnedToCore(
        (TaskFunction_t)&handleInteruptTaskCallerFn,
        taskName,
        2048,
        this,
        5,
        &canInterruptTaskHandle,
        0
    );
}

#endif
