#include <stdio.h>

#include <driver/gpio.h>
#include <driver/spi_slave.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <neopixel.h>

DRAM_ATTR static const char* tag = "EZDC";

static const uint64_t kMISOPin = GPIO_NUM_4;
static const uint64_t kMOSIPin = GPIO_NUM_7;
static const uint64_t kClkPin = GPIO_NUM_6;
static const uint64_t kDirPin = GPIO_NUM_1;
static const uint64_t kStepPin = GPIO_NUM_2;
static const uint64_t kDiagPin = GPIO_NUM_3;
static const uint64_t kCSPin = GPIO_NUM_5;
static const uint64_t kEnPin = GPIO_NUM_8;

void IRAM_ATTR postSetupCallback(spi_slave_transaction_t* transaction) {
    ESP_DRAM_LOGI(tag, "Post setup");
}

void IRAM_ATTR postTransactionCallback(spi_slave_transaction_t* transaction) {
    ESP_DRAM_LOGI(tag, "Post transaction");
}

alignas(32) static uint8_t transmitBuffer[] = "My Tallest!";

extern "C" {
void app_main(void) {
    esp_err_t err;
    spi_bus_config_t busConfig = {.mosi_io_num = kMOSIPin,
                                  .miso_io_num = kMISOPin,
                                  .sclk_io_num = kClkPin,
                                  .quadwp_io_num = -1,
                                  .quadhd_io_num = -1,
                                  .data4_io_num = -1,
                                  .data5_io_num = -1,
                                  .data6_io_num = -1,
                                  .data7_io_num = -1,
                                  .data_io_default_level = 0,
                                  .max_transfer_sz = 0,
                                  .flags = SPICOMMON_BUSFLAG_SLAVE | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_SCLK,
                                  .isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
                                  .intr_flags = 0};
    spi_slave_interface_config_t slaveConfig = {
        .spics_io_num = kCSPin,
        .flags = 0,
        .queue_size = 8,
        .mode = 0,
        .post_setup_cb = postSetupCallback,
        .post_trans_cb = postTransactionCallback,
    };
    err = spi_slave_initialize(SPI2_HOST, &busConfig, &slaveConfig, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK_WITHOUT_ABORT(err);

    while (true) {
        ESP_LOGI(tag, "Hello world");
        spi_slave_transaction_t transaction = {
            .flags = 0,
            .length = 8 * sizeof(transmitBuffer) / sizeof(transmitBuffer[0]),
            .trans_len = 8 * sizeof(transmitBuffer) / sizeof(transmitBuffer[0]),
            .tx_buffer = transmitBuffer,
            .rx_buffer = nullptr,
            .user = nullptr,
        };
        spi_slave_transmit(SPI2_HOST, &transaction, 100000000 / portTICK_PERIOD_MS);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}
}
