
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"
#include "serial_mt.h"
#include "evse_api.h"
#include "currentshaper.h"
#include "energy_meter.h"
//#include "app_main.h"
//#include "sync_master.h"

#define BUF_SIZE 128

#define TXD_PIN (GPIO_NUM_17)
#define RXD_PIN (GPIO_NUM_16)

#define VOLTAGE_CURRENT1_ATTR 0x0006
#define VOLTAGE_CURRENT2_ATTR 0x0007
#define VOLTAGE_CURRENT3_ATTR 0x0008

// static uint8_t msg[128];

static const char *TAG = "serial_mt";

static uart_port_t port = -1;

static TaskHandle_t serial_mt_task = NULL;

static const int RX_BUF_SIZE = 14;

static void serial_mt_task_func(void *param)
{
    ESP_LOGI(TAG, "serial_mt_task_func");

    uint8_t *buff = (uint8_t *)malloc(RX_BUF_SIZE + 1);

    unsigned long currentMillis = pdTICKS_TO_MS(xTaskGetTickCount()) - 120000;

    while (1)
    {
        const int rxBytes = uart_read_bytes(UART_NUM_1, buff, RX_BUF_SIZE, 1000 / portTICK_PERIOD_MS);
        if (rxBytes >= 10)
        {
            //ESP_LOGI(TAG, "Read %d bytes: '%s'", rxBytes, buff);
            //ESP_LOG_BUFFER_HEXDUMP(TAG, buff, rxBytes, ESP_LOG_INFO);

            uint8_t idmsg = buff[0];
            uint16_t code = buff[1] + (buff[2] << 8);
            uint8_t size = buff[4];
            uint32_t power = 0;
            uint32_t current = 0;
            uint32_t volt = 0;

            float maxcurrent = 0;
            float l1current = 0;
            float l2current = 0;
            float l3current = 0;

            //ESP_LOGI(TAG, "Msg id: %d code 0x%04hx size %d ", idmsg, code, size);

            if (size == 8)
            {
                power = buff[12] + (buff[11] << 8) + (buff[10] << 16); // + (buff[9] << 24);
                ESP_LOGI(TAG, "VOLTAGE_CURRENT_ATTR Power value %" PRIu32 " ", power);
                current = buff[9] + (buff[8] << 8) + (buff[7] << 16); // + (buff[9] << 24);
                ESP_LOGI(TAG, "VOLTAGE_CURRENT_ATTR Current value %" PRIu32 " ", current);
                volt = buff[6] + (buff[5] << 8); // + (buff[4] << 16);// + (buff[9] << 24);
                ESP_LOGI(TAG, "VOLTAGE_CURRENT_ATTR Voltage value %" PRIu32 " ", volt);

                if (code == VOLTAGE_CURRENT1_ATTR)
                {
                    l1current = current / 100.0f;
                }
                else if (code == VOLTAGE_CURRENT2_ATTR)
                {
                    l2current = current / 100.0f;
                }
                else if (code == VOLTAGE_CURRENT3_ATTR)
                {
                    l3current = current / 100.0f;
                }
                else
                {
                    ESP_LOGW(TAG, "Error code %d ", code);
                    // continue;
                }
                maxcurrent = (l1current > l2current) ? l1current : l2current;
                maxcurrent = (maxcurrent > l3current) ? maxcurrent : l3current;

                ESP_LOGI(TAG, "maxcurrent value %f ", maxcurrent);

                //send_grid_current(maxcurrent);

                if (evse_state_is_charging(evse_get_state()))
                {
                    setMaxGridCurrent(grid_get_max_current() * 10);
                    setLiveGridCurrent((int)maxcurrent);

                    /*
                    if (pdTICKS_TO_MS(xTaskGetTickCount()) - currentMillis > 120000)
                    {
                        push_grid_power(power / 1000.0f);

                        push_grid_current(l1current / 10.0f);

                        push_grid_volt(volt / 10.0f);

                        currentMillis = pdTICKS_TO_MS(xTaskGetTickCount());
                    }*/

                }
            }
        }
    }
    free(buff);
}

int sendData(const char *data)
{
    const int len = strlen(data);
    const int txBytes = uart_write_bytes(UART_NUM_1, data, len);
    ESP_LOGI(TAG, "Wrote %d bytes", txBytes);
    return txBytes;
}

void serial_mt_start()
{

    ESP_LOGI(TAG, "Starting MT Serial");

    const uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };

    esp_err_t err = uart_param_config(UART_NUM_1, &uart_config);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "uart_param_config() returned 0x%x", err);
        return;
    }
    err = uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "uart_driver_install() returned 0x%x", err);
        return;
    }
    ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));

    // xTaskCreate(rx_task, "uart_rx_task", 1024 * 4, NULL, configMAX_PRIORITIES, NULL);
    xTaskCreate(serial_mt_task_func, "serial_mt_task", 4 * 1024, NULL, 5, &serial_mt_task);
}

void serial_mt_stop(void)
{
    ESP_LOGI(TAG, "Stopping");

    if (serial_mt_task)
    {
        vTaskDelete(serial_mt_task);
        serial_mt_task = NULL;
    }

    if (port != -1)
    {
        uart_driver_delete(port);
        port = -1;
    }
}