#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <syslog.h>
#include <time.h>
#include <errno.h>

#include "dy_utils/dy_common.h"
#include "dy_utils/dy_pp.h"
#include "rs485_slave_common.h"

static int load_server_topic_config(mqtt_server_topic_t *mqtt_server_topic, char *cfg_file)
{
    char *data = NULL;
    int lens = 0;
    cJSON *root = NULL;
    int ret = -1;

    if (cfg_file == NULL)
    {
        dy_syslog(LOG_ERR, "cfg_file:%s not exist", cfg_file);
        goto out;
    }

    data = read_file_data_and_lens(cfg_file, &lens);
    if (data == NULL)
    {
        dy_syslog(LOG_ERR, "read cfg file %s error", cfg_file);
        goto out;
    }

    root = cJSON_Parse(data);
    if (!root)
    {
        char *new = malloc(lens);
        if (new != NULL)
        {
            lnxall_decrypt_string((unsigned char *) data, lens, (unsigned char *) new);
            free(data);
            data = new;
            root = cJSON_Parse(data);
        }

        if (!root)
        {
            dy_syslog(LOG_ERR, "parse cfg file %s error", cfg_file);
            goto out;
        }
    }

    GET_JSON_VALUE_STRING(root, "host", mqtt_server_topic->addr);
    GET_JSON_VALUE_INT(root, "port", mqtt_server_topic->port);
    GET_JSON_VALUE_STRING(root, "user", mqtt_server_topic->user);
    GET_JSON_VALUE_STRING(root, "pass", mqtt_server_topic->pass);
    GET_JSON_VALUE_INT(root, "qos", mqtt_server_topic->qos);
    GET_JSON_VALUE_INT(root, "keepalive", mqtt_server_topic->keepalive);
    GET_JSON_VALUE_STRING(root, "topic", mqtt_server_topic->topic);

    cJSON_Delete(root);
    ret = 0;

out:
    if (data)
    {
        free(data);
    }

    return ret;
}

static int rs485_slave_init(rs485_slave_var_t *var)
{
    int i;
    int port_numbers;
    int port;

    get_board_sn(var->sn_str);
    var->board_name = get_board_name();
    if (load_objects_cfg(&var->object_table, OBJECTS_CFG_PATH) == -1)
    {
        dy_syslog(LOG_ERR, "load object cfg fail");
    }
    rs485_slave_load_config(var);
    if (load_server_topic_config(&var->mqtt_server_topic, MQTT_SERVER_TOPIC_FILE) == -1)
    {
        dy_syslog(LOG_ERR, "load server topic cfg fail");
    }

    if (strcmp(var->board_name, BOARD_WOOLINK_MT7628) == 0)
    {
        port_numbers = 2;
    } else {
        port_numbers = 4;
    }

    for (i = 0; i < port_numbers; i++)
    {
        port = rs485_slave_port_map(var->rs485_slave_ports_cfg.rs485_slave_port_cfg[i].port);

        if (var->rs485_slave_ports_cfg.rs485_slave_port_cfg[i].disable == 0)
        {
            rs485_slave_start_thread(var, &var->rs485_slave_ports_cfg.rs485_slave_port_cfg[i], port);
        }
    }

    var->poll_timer = my_timer_create();
    if (var->poll_timer > 0)
    {
        my_timer_set(var->poll_timer, 1, 5000);
    }

    return 0;
}

static int rs485_slave_poll(rs485_slave_var_t *var)
{
    TIMER_CONFIRM(var->poll_timer);

    return 0;
}

static void rs485_slave_loop(rs485_slave_var_t *var)
{
    int ret = -1, maxfd;
    fd_set  rset;
    struct timeval timeout;

    while (1)
    {
        SELECT_INIT();
        SELECT_ADD_FD(var->poll_timer);
        timeout.tv_usec = 0;
        timeout.tv_sec = 2;
        ret = select(maxfd + 1, &rset, 0, 0, &timeout);
        if (ret < 0)
        {
            int error = errno;
            printf("errno %d\n", error);
            if (error == EINTR)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else if (ret > 0)
        {
            if (var->poll_timer > 0 && FD_ISSET(var->poll_timer, &rset))
            {
                FD_CLR(var->poll_timer, &rset);
                rs485_slave_poll(var);
            }
        }
    }
}

int main(int argc, char *argv[])
{
    rs485_slave_var_t var = {0};

    memset(&var, 0, sizeof(var));
    openlog("rs485_slave", LOG_PID, LOG_DAEMON);

    rs485_slave_init(&var);
    rs485_slave_loop(&var);

    return 0;
}
