#include "screen_show.h"
#include "tm1640_gpio.h"
#include "sub_functions.h"
#include "dy_utils/dy_common.h"
#include "mqtt_client.h"

#define SINGLE_CELL_FAULT_ALARM_MASK    0x03cc  // E1
#define COMMUNICATION_ALARM_MASK        0x0030  // E2
#define SOC_LOW_ALARM                   20      // E3
#define SYSTEM_TOTAL_VOL_ALARM_MASK     0x0003  // E4
#define LOOP_FAULT_ALARM_MASK           0x007f  // E5
#define SYSTEM_TEM_HIGH_ALARM_MASK      0x1800  // E6

static bool is_single_cell_fault_alarm_trigger(int reg_val)
{
    if ((reg_val & SINGLE_CELL_FAULT_ALARM_MASK) != 0)
    {
        return true;
    }

    return false;
}

static bool is_communication_alarm_trigger(int reg_val)
{
    if ((reg_val & COMMUNICATION_ALARM_MASK) != 0)
    {
        return true;
    }

    return false;
}

static bool is_soc_low_alarm_trigger(int reg_val)
{
    if (reg_val < SOC_LOW_ALARM)
    {
        return true;
    }

    return false;
}

static bool is_system_total_vol_alarm_trigger(int reg_val)
{
    if ((reg_val & SYSTEM_TOTAL_VOL_ALARM_MASK) != 0)
    {
        return true;
    }

    return false;
}

static bool is_loop_fault_alarm_trigger(int reg_val)
{
    if ((reg_val & LOOP_FAULT_ALARM_MASK) != 0)
    {
        return true;
    }

    return false;
}

static bool is_system_tem_high_alarm_trigger(int reg_val)
{
    if ((reg_val & SYSTEM_TEM_HIGH_ALARM_MASK) != 0)
    {
        return true;
    }

    return false;
}

void handle_work_state(tm1640_t *tm1640)
{
    static int rackChgStateLast = -1;

    if (rackChgStateLast == tm1640->rackChgState) {
        return;
    }

    rackChgStateLast = tm1640->rackChgState;
    printf("rackChgStateLast: %d\n", rackChgStateLast);

    if (tm1640->rackChgState == 0)
    {
        change_state_to_standby(tm1640->gpio_handler);
    }
    else if (tm1640->rackChgState == 1)
    {
        change_state_to_discharging(tm1640->gpio_handler);
    }
    else if (tm1640->rackChgState == 2)
    {
        change_state_to_charging(tm1640->gpio_handler);
    }
    else
    {
        dy_syslog(LOG_ERR, "Invalid value of rackChgState\n");
    }
}

void handle_soc_showing(tm1640_t *tm1640)
{
    static double rackSocLast = 1001;   // Max value is 1000
    if (rackSocLast == tm1640->rackSoc) {
        return;
    }

    rackSocLast = tm1640->rackSoc;
    int soc_int = (int)tm1640->rackSoc;
    printf("rackSocLast: %lf\n", rackSocLast);
    printf("soc_int: %d\n", soc_int);

    set_soc_circle(tm1640->gpio_handler, soc_int);
    set_soc_value(tm1640->gpio_handler, soc_int);
}

void handle_heat_state(tm1640_t *tm1640)
{
    printf("=====heatStatus: %d\n", tm1640->heatStatus);

    static int heatStatusLast = -1;

    if (heatStatusLast == tm1640->heatStatus) {
        return;
    }

    heatStatusLast = tm1640->heatStatus;
    dy_syslog(LOG_INFO, "heatStatusLast: %d",heatStatusLast);
    
    if (tm1640->heatStatus == 0)
    {
        turn_sun_off(tm1640->gpio_handler);
    }
    else
    {
        turn_sun_on(tm1640->gpio_handler);
    }
}

void handle_warning_report(tm1640_t *tm1640)
{
    static int entry_times = 0;

    if (entry_times < 5) {  // 经实测大概每3s会执行一次后面的代码，以满足每个告警显示3s的要求
        entry_times++;
        return;
    }
    entry_times = 0;

    if (tm1640->cnt_warning == 0) {
        tm1640->show_inx = 0;
        clear_alarm(tm1640->gpio_handler);
        return;
    }

    int i;
    for (i = 0; i < tm1640->cnt_warning; i++) {
        dy_syslog(LOG_INFO, "buf_warning[%d]: %d\n", i, tm1640->buf_warning[i]);
    }

    if (tm1640->show_inx >= (tm1640->cnt_warning)) {
        tm1640->show_inx = 0;       // Set show_inx to 0 for loop display
    }

    clear_alarm(tm1640->gpio_handler);
    set_warning_level(tm1640->gpio_handler, tm1640->buf_warning[tm1640->show_inx]);
    tm1640->show_inx++;
}

void set_turn_on_screen_time(tm1640_t *tm1640, int cnt)
{
    tm1640->remainLightCnt = cnt;
}

// static int publish_to_south(ipc_session_t *sesson)
// {
//     if (sesson == NULL) {
//         dy_syslog(LOG_ERR, "Invalid argument!!!");
//         return -1;
//     }

//     char topic[TOPIC_MAX_LEN] = {0};
//     char dev_sn[50] = {0};
//     GET_SN_PROC
//     cJSON *root = cJSON_CreateObject();
//     if (root == NULL)
//     {
//         dy_syslog(LOG_ERR, "cJSON_CreateObject failed!!!");
//         return -1;
//     }

//     snprintf(dev_sn, 50, "%s%s", sn, "_Rack_1");
//     cJSON_AddStringToObject(root, "identifier", "SetButtonStatus");
//     cJSON_AddNumberToObject(root, "ButtonStatus", 0);
//     cJSON_AddStringToObject(root, "sn", dev_sn);
//     cJSON_AddStringToObject(root, "requester", "local");
//     cJSON_AddNumberToObject(root, "mi", 1);
//     cJSON_AddNumberToObject(root, "timestamp", time(NULL));
//     char *str = (cJSON_Print(root));
//     cJSON_Delete(root);

//     snprintf(topic, TOPIC_MAX_LEN, "ipc/%s/RS485_1/device/%s%s/data/Set_Rglt", sn, sn, "_Rack_1");
//     dy_syslog(LOG_DEBUG, "pub:topic  :%s", topic);
//     dy_syslog(LOG_DEBUG, "pub:payload:%s", str);
//     ipc_session_publish(sesson, topic, (unsigned char *)str, (int)strlen(str));

//     if (str) {
//         free(str);  str = NULL;
//     }

//     return 0;
// }

void handle_turn_creen_on_button(tm1640_t *tm1640)
{
    static int buttonStatusLast = -1;

    if (buttonStatusLast == tm1640->buttonStatus) {
        return;
    }

    buttonStatusLast = tm1640->buttonStatus;
    dy_syslog(LOG_INFO, "buttonStatusLast: %d", buttonStatusLast);

    if (tm1640->buttonStatus > 0) {
        set_turn_on_screen_time(tm1640, DEFAULT_TIME);
        publish_to_south(tm1640->session, "SetButtonStatus", "ButtonStatus", 0);
    }
}