#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sub_functions.h"
#include "mqtt_client.h"
#include "screen_show.h"
#include "dy_utils/dy_common.h"


#define DEFAULT_DIN     5
#define DEFAULT_SCLK    4
#define DEFAULT_LIGHT   7

static void led_start_init(tm1640_t *tm1640)
{
    clean_screen(tm1640->gpio_handler);
    tm1640_gpio_command(tm1640->gpio_handler, TM1640_PWM(DEFAULT_LIGHT));
    turn_percent_on(tm1640->gpio_handler);
    turn_wifi_on(tm1640->gpio_handler);
    turn_sun_off(tm1640->gpio_handler);
    turn_outside_circle_on(tm1640->gpio_handler);
}

static void tm1640_init(tm1640_t *tm1640)
{
    if (tm1640 == NULL) {
        return;
    }

    set_turn_on_screen_time(tm1640, DEFAULT_TIME);
    led_start_init(tm1640);
    tm1640_mqtt_client_init(tm1640);

    tm1640->period_poll_timer = my_timer_create();
    if (tm1640->period_poll_timer > 0)
    {
        my_timer_set(tm1640->period_poll_timer, 1, 500);
    }
}

int turn_off_screen(tm1640_t *tm1640)
{
    static int remainLightCntLast = -1;

    if ((remainLightCntLast == tm1640->remainLightCnt) && (tm1640->remainLightCnt == 0)) {
        return 1;
    }

    remainLightCntLast = tm1640->remainLightCnt;
    dy_syslog(LOG_INFO, "remainLightCntLast: %d", remainLightCntLast);

    if (tm1640->remainLightCnt > 0) {
        tm1640->remainLightCnt--;
        return 0;
    } else {
        tm1640_gpio_command(tm1640->gpio_handler, TM1640_OFF);
        return 1;
    }

    return 0;
}

static int period_service_poll(tm1640_t *tm1640)
{
    static int i = 0;
    TIMER_CONFIRM(tm1640->period_poll_timer);

    if (tm1640->is_node_conf_recv) {
        printf("i: %d\n", i);
        i++;
    }

    if (i > 60) {
        i = 0;
        tm1640->is_node_conf_recv = 0;
        printf("call set_pcs_type_and_pack_num\n");
        set_pcs_type_and_pack_num(tm1640);
    }

    

    handle_turn_creen_on_button(tm1640);

    if (turn_off_screen(tm1640)) {
        return 0;
    }

    tm1640_gpio_command(tm1640->gpio_handler, TM1640_PWM(DEFAULT_LIGHT));
    handle_work_state(tm1640);
    handle_soc_showing(tm1640);
    handle_heat_state(tm1640);
    handle_warning_report(tm1640);

    return 0;
}

static void tm1640_loop(tm1640_t *tm1640)
{
    int ret = -1, maxfd, i;
    fd_set rset;
    struct timeval timeout;

    while (1)
    {
        SELECT_INIT();
        SELECT_ADD_FD(tm1640->period_poll_timer);
        timeout.tv_usec = 0;
        timeout.tv_sec = 5;

        ret = select(maxfd + 1, &rset, 0, 0, &timeout);
        if (ret < 0)
        {
            int error = errno;
            dy_syslog(LOG_ERR, "hello errno %d\n", error);

            if (error == EINTR)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else if (ret > 0)
        {
            if (tm1640->period_poll_timer > 0 && FD_ISSET(tm1640->period_poll_timer, &rset))
            {
                FD_CLR(tm1640->period_poll_timer, &rset);
                period_service_poll(tm1640);
            }
        }
    }
}

/*
* The function is used for shorten start up time.
* The default value of bootdelay is 5 seconds.
* The function will set bootdelay to 1 second.
*/
static void set_bootdelay_to_1sec(void)
{
    FILE *fp;
    char buffer[50];
    fp = popen("fw_printenv bootdelay", "r");
    fgets(buffer, sizeof(buffer), fp);
    pclose(fp);

    dy_syslog(LOG_INFO, "buffer: %s", buffer);

    if (0 != strcmp(buffer, "bootdelay=1\n")) {
        system("fw_setenv bootdelay 1");
        dy_syslog(LOG_INFO, "Set bootdelay to 1");
    } else {
        dy_syslog(LOG_INFO, "Do not set bootdelay");
    }
}

int main(int argc, char **argv)
{
    tm1640_t tm1640;
    memset(&tm1640, 0, sizeof(tm1640));

    tm1640.gpio_handler = tm1640_gpio_init(DEFAULT_DIN, DEFAULT_SCLK);
    if(!tm1640.gpio_handler) {
        dy_syslog(LOG_ERR, "Could not initialize tm1640 on GPIOs");
        return -1;
    }

    set_bootdelay_to_1sec();
    tm1640_init(&tm1640);
    tm1640_loop(&tm1640);

    return 0;
}