#include <sys/cdefs.h>
#include <stdio.h>
#include <esp_err.h>

#include "platform.h"
#include "st25R3911_interrupt.h"

#include "pollingtagdetect.h"

#define SPI_CLK  5
#define SPI_MOSI 6
#define SPI_MISO 7

#define ESP_INTR_FLAG_DEFAULT 0

portMUX_TYPE CommProtectLock = portMUX_INITIALIZER_UNLOCKED;

static void gpio_isr_handler(void *arg) {
    st25r3911Isr();
}

esp_err_t init_gpio(void) {
    gpio_config_t io_conf = {};
    //disable interrupt
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //set as output mode
    io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
    //bit mask of the pins that you want to set,e.g.GPIO18/19
    io_conf.pin_bit_mask = (1ULL << ST25R391X_SS_PIN);
    //disable pull-down mode
    io_conf.pull_down_en = 0;
    //disable pull-up mode
    io_conf.pull_up_en = 0;
    //configure GPIO with the given settings
    esp_err_t ret = gpio_config(&io_conf);
    ESP_ERROR_CHECK(ret);


    //interrupt of rising edge
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    //bit mask of the pins, use GPIO4/5 here
    io_conf.pin_bit_mask = (1ULL << ST25R391X_INT_PIN);
    //set as input mode
    io_conf.mode = GPIO_MODE_INPUT;
    //enable pull-up mode
//    io_conf.pull_up_en = 1;
    ret = gpio_config(&io_conf);
    ESP_ERROR_CHECK(ret);


    ret = gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    ESP_ERROR_CHECK(ret);
    //hook isr handler for specific gpio pin
    ret = gpio_isr_handler_add(ST25R391X_INT_PIN, gpio_isr_handler, NULL);
    ESP_ERROR_CHECK(ret);

    return ret;
}

esp_err_t init_spi(void) {
    spi_bus_config_t buscfg = {
            .miso_io_num=SPI_MISO,
            .mosi_io_num=SPI_MOSI,
            .sclk_io_num=SPI_CLK,
            .quadwp_io_num=-1,
            .quadhd_io_num=-1,
    };
    esp_err_t ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);

    spi_device_interface_config_t devcfg = {
            .clock_speed_hz=SPI_MASTER_FREQ_8M,           //Clock out at 4 MHz
            .mode=1,                                //SPI mode 1
            .spics_io_num=-1,               //CS pin
            .queue_size=1,                          //We want to be able to queue 7 transactions at a time
    };

    spi_device_handle_t spi;
    ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);
    st25r3911_spi_init(spi);

    return ret;
}

_Noreturn static void cycle_task(void *arg) {
    while (1) {
        TagDetectCycle();
//        ESP_LOGI("cycle_task", "running tag detect cycle_task");
    }
}

void app_main(void) {
    ESP_ERROR_CHECK(init_gpio());
    ESP_LOGI("main", "init_gpio done");
    ESP_ERROR_CHECK(init_spi());
    ESP_LOGI("main", "init_spi done");
    ESP_ERROR_CHECK(TagDetectInit());
    ESP_LOGI("main", "TagDetectInit done");
    xTaskCreate(cycle_task, "cycle_task", 4096, NULL, tskIDLE_PRIORITY, NULL);
    ESP_LOGI("main", "cycle_task sheduled");
}
