//================================================================================================
/// @file main.cpp
///
/// @brief Defines `main` for the seeder example
/// @details This example is meant to use all the major protocols in a more "complete" application.
/// @author Adrian Del Grosso
///
/// @copyright 2023 The Open-Agriculture Developers
//================================================================================================
#include "seeder.hpp"
#include "shared.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "network_manager.h"
#include "nvs_flash.h"


#include <SmartLeds.h>

#include <stdio.h>
#include "driver/gpio.h"

#define OLIMEX_BUT_PIN GPIO_NUM_4

const int LED_COUNT = 64 + 256;
const int DATA_PIN = 0;
const int CHANNEL = 0;


// SmartLed -> RMT driver (WS2812/WS2812B/SK6812/WS2813)
SmartLed leds(LED_WS2812B, LED_COUNT, DATA_PIN, CHANNEL, DoubleBuffer);


volatile uint8_t hue = 0;
bool trigger_rainbow = false;
uint8_t brightness = 1;

void delay(int ms) { vTaskDelay(pdMS_TO_TICKS(ms)); }
uint32_t millis() { return xTaskGetTickCount(); }

#define OLIMEX_REL1_PIN GPIO_NUM_32
#define OLIMEX_REL2_PIN GPIO_NUM_33
#define OLIMEX_BUT_PIN GPIO_NUM_4

/* You can run menuconfig to change relay */
#if defined CONFIG_RELAY_1
#define RELAY_GPIO OLIMEX_REL1_PIN
#else
#define RELAY_GPIO OLIMEX_REL2_PIN
#endif

void showColor() {
    // Use HSV to create nice gradient
    for (int i = 0; i != LED_COUNT; i++)
        leds[i] = Hsv { hue, 255, brightness };
    leds.show();
}

/**
 * @brief button_task  Task to handle button press
 */
void button_task(void* arg)
{
    while (1)
    {
        if (gpio_get_level(OLIMEX_BUT_PIN) == 0)
        {
            gpio_set_level(RELAY_GPIO, 1);
            printf("Button pressed\n");
            brightness = 100;
            showColor();
            while (gpio_get_level(OLIMEX_BUT_PIN) == 0)
            {
                vTaskDelay(pdMS_TO_TICKS(50)); // Debounce delay
            }
            gpio_set_level(RELAY_GPIO, 0);
            brightness = 1; 
            showColor();
            vTaskDelay(pdMS_TO_TICKS(50)); // Debounce delay
        }
        vTaskDelay(pdMS_TO_TICKS(50)); // Polling delay
    }
}

void setup() {
     /* Make pads GPIO */
    gpio_reset_pin(RELAY_GPIO);
    gpio_reset_pin(OLIMEX_BUT_PIN);

    /* Set the Relay as a push/pull output */
    gpio_set_direction(RELAY_GPIO, GPIO_MODE_OUTPUT);

    /* Set Button as input */
    gpio_set_direction(OLIMEX_BUT_PIN, GPIO_MODE_INPUT);

    /* Create button task */
    xTaskCreate(button_task, "button_task", 2048, NULL, 10, NULL);

    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    //wifi_init_sta();
    //mqtt_app_start();
}



void showRgb() {
    leds[0] = Rgb { 255, 0, 0 };
    leds[1] = Rgb { 0, 255, 0 };
    leds[2] = Rgb { 0, 0, 255 };
    leds[3] = Rgb { 0, 0, 0 };
    leds[4] = Rgb { 255, 255, 255 };
    leds.show();
}

void colorTask(void *pvParameters) {
    while (true) {
        showColor();
        delay(50);
    }
}

void hueControlTask(void *pvParameters) {
    while (true) {
        // Increment hue and wrap around at 255
        hue = (hue + 1) % 256;
        delay(50);  // Adjust delay as needed for hue change rate
    }
}


static const char *TAG = "seeder_example";
static TaskHandle_t xTaskToNotify = NULL;
static bool running = true;

void signal_handler_task(void *pvParameters) {
    while (running) {
        // Wait for the notification
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        ESP_LOGI(TAG, "Signal received, stopping...");
        running = false;
    }
    vTaskDelete(NULL);
}

extern "C" void app_main() {
    setup();
    Seeder seederExample;
    xTaskCreate(signal_handler_task, "SignalHandlerTask", 2048, NULL, 5, &xTaskToNotify);

    // Create the color update task
    //xTaskCreate(colorTask, "Color Task", 1024, NULL, 11, NULL);
    
    // Create the hue control task
    xTaskCreate(hueControlTask, "Hue Control Task", 1024, NULL, 11, NULL);
    


    if (seederExample.initialize()) {
        ESP_LOGE(TAG, "Initialization Successful, CAN interface ready!");
        while (running) {
            seederExample.update();

            if (new_message_received) {
                trigger_effect();
                printf("Button pressed\n");
                brightness = 100;
                showColor();

                seederExample.sendCanMessage();
                
                vTaskDelay(pdMS_TO_TICKS(1000)); 
                brightness = 1; 
                new_message_received = false;
                showColor();
            }

            vTaskDelay(pdMS_TO_TICKS(10));
        }
        seederExample.terminate();
    } else {
        ESP_LOGE(TAG, "Initialization failed, CAN interface might be missing.");
    }

    // Notify the signal handler task to stop
    if (xTaskToNotify != NULL) {
        xTaskNotifyGive(xTaskToNotify);
    }
}