#pragma once

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

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

void transactionTaskWrapperFn(void *pvParameters) {
    MCP2521_HardwareHandleFactory_ESPBus *factory = (MCP2521_HardwareHandleFactory_ESPBus *)pvParameters;
    factory->transactionTaskFn();

}

MCP2521_HardwareHandleFactory_ESPBus::MCP2521_HardwareHandleFactory_ESPBus(
    spi_host_device_t spi_host,
    gpio_num_t mosi, 
    gpio_num_t miso, 
    gpio_num_t sclk
) {
    this->spi_host = spi_host;
    this->mosi = mosi;
    this->miso = miso;
    this->sclk = sclk;

    
    gpio_install_isr_service(0);

    MCP2521_HardwareHandle_ESP::initSPIBus(spi_host, mosi, miso, sclk, &bus_config);
    
    spi_queue = xQueueCreate(12, sizeof(spi_message_t));
    xTaskCreatePinnedToCore(
        (TaskFunction_t)&transactionTaskWrapperFn,
        "transactionTask",
        2048,
        this,
        3,
        &transactionTaskHandle,
        0
    );
}

void MCP2521_HardwareHandleFactory_ESPBus::transactionTaskFn() {
    spi_message_t message;

    while(true) {
        xQueueReceive(spi_queue, &message, portMAX_DELAY);
        spi_device_transmit(message.spi_device_handle, message.transaction);
    }
}

MCP2521_HardwareHandle_ESPBus MCP2521_HardwareHandleFactory_ESPBus::create(
    gpio_num_t int_pin,
    gpio_num_t cs
) {
    return MCP2521_HardwareHandle_ESPBus(
        spi_queue,
        spi_host,
        &bus_config,
        cs,
        int_pin
    );
}


#endif