#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include "dm_common.h"

static void msg_evt_gateway_net_port_info(dm_var_t *var)
{
    char *buff = NULL;
    char topic[192] = {0};
    char  exec_cmd[256] = {0};

    sprintf(exec_cmd, "%s/%s", NET_BASH_PATH, "fetch_port_status.sh");
    system_reply(exec_cmd, &buff);
    if (!buff)
    {
        dy_syslog(LOG_ERR, "system run \'%s\' fail !", exec_cmd);
        return;
    }
    snprintf(topic, sizeof(topic), "G/%s/gateway/device/%s/service/%s", var->sn_str, var->sn_str, TOPIC_EVT_NETWORKINFO);
    ipc_session_publish(var->session, topic, buff, strlen(buff));
    free(buff);
}

static void msg_evt_gateway_cpu_mem_info(dm_var_t *var)
{
    char *buff = NULL;
    char  exec_cmd[256] = {0};
    char topic[192] = {0};

    sprintf(exec_cmd, "%s/%s", NET_BASH_PATH, "fetch_cpu_mem_status.sh");
    system_reply(exec_cmd, &buff);
    if (!buff)
    {
        dy_syslog(LOG_ERR, "system run \'%s\' fail !", exec_cmd);
        return;
    }

    snprintf(topic, sizeof(topic), "G/%s/gateway/device/%s/service/%s", var->sn_str, var->sn_str, TOPIC_EVT_CPUMEMINFO);
    ipc_session_publish(var->session, topic, buff, strlen(buff));
    free(buff);
}

/*
static void msg_evt_gateway_lora_info(dm_var_t *var)
{
    char *str = NULL;
    char topic[TOPIC_MAX_LEN] = {0};
    str = read_file_data(LORA_MODULE_SATUS_CACHE"/status.json");
    if (!str)
    {
        return;
    }

    snprintf(topic, TOPIC_MAX_LEN, "G/%s/gateway/device/%s/service/%s", var->sn_str, var->sn_str, TOPIC_EVT_LORAINFO);
    ipc_session_publish(var->session, topic, str, strlen(str));
    free(str);
}
*/

static void msg_evt_radio_status(dm_var_t *var)
{
    char  exec_cmd[256] = {0};
    char topic[192] = {0};
    char *buff = NULL;

    sprintf(exec_cmd, "%s/%s status", NET_BASH_PATH, "fetch_wireless_status.sh");
    system_reply(exec_cmd, &buff);
    if (!buff)
    {
        dy_syslog(LOG_ERR, "system run \'%s\' fail !", exec_cmd);
        return;
    }
    snprintf(topic, sizeof(topic), "G/%s/gateway/device/%s/service/%s", var->sn_str, var->sn_str, TOPIC_EVT_RADIOSTATUS);
    ipc_session_publish(var->session, topic, buff, strlen(buff));
    free(buff);
}

static void msg_evt_vap_status(dm_var_t *var)
{
    char  exec_cmd[256] = {0};
    char topic[192] = {0};
    char *buff = NULL;

    sprintf(exec_cmd, "%s/%s status", NET_BASH_PATH, "fetch_vap_status.sh");
    system_reply(exec_cmd, &buff);
    if (!buff)
    {
        dy_syslog(LOG_ERR, "system run \'%s\' fail !", exec_cmd);
        return;
    }
    snprintf(topic, sizeof(topic), "G/%s/gateway/device/%s/service/%s", var->sn_str, var->sn_str, TOPIC_EVT_WIRELESSSTATIONSTATUS);
    ipc_session_publish(var->session, topic, buff, strlen(buff));
    free(buff);
}

static int param_status_poll(dm_var_t *var)
{
    TIMER_CONFIRM(var->module_slow_timer_fd);
    time_t now = time(NULL);

    if (((now >= var->last_report_state + var->report_arg.intv) && (var->report_arg.intv >= 1) && (now < var->report_arg.stop_times)) || 
            (now - var->last_report_state >= 1800)) //小于3s可能会造成发送过于平凡，同时隔一段时间上报一下数据
    {
        var->last_report_state = now;
        msg_evt_gateway_net_port_info(var);
        //msg_evt_gateway_lora_info(var);
        msg_evt_gateway_cpu_mem_info(var);
        msg_evt_radio_status(var);
        msg_evt_vap_status(var);
    }

    return 0;
}

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

    while (1)
    {
        SELECT_INIT();
        SELECT_ADD_FD(var->module_slow_timer_fd);
        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->module_slow_timer_fd > 0 && FD_ISSET(var->module_slow_timer_fd, &rset))
            {
                FD_CLR(var->module_slow_timer_fd, &rset);
                param_status_poll(var);
            }
        }
    }
}

static void dm_subscribe_all(dm_var_t *var)
{
    ipc_session_t *ipc_session = var->session;
    char topic[TOPIC_MAX_LEN] = {0};

    snprintf(topic, TOPIC_MAX_LEN, "M/+/%s/device/%s/service/%s", TOPIC_GATEWAY_CONFIG, var->sn_str, TOPIC_SET_GATEWAYSTATUSINTV);
    ipc_session_subscribe(ipc_session, topic);
}

static int dm_mqtt_handle_recv_msg(void *obj, ipc_msg_t *mqtt_msg)
{
    dm_var_t *var = (dm_var_t *)obj;

    dy_syslog(LOG_DEBUG, " MQTT client: received MQTT topic:%s payload length:%d",
              mqtt_msg->topic, mqtt_msg->payloadLen);
    dm_handle_mqtt_data(var, mqtt_msg);
    return 0;
}

// 建立与内部broker之间的MQTT连接
static int dm_mqtt_client_init(dm_var_t *var)
{
    char clientId[128] = {0};

    snprintf(clientId, sizeof(clientId), "INT_dm_%s", var->sn_str);
    var->session = ipc_session_new(clientId, (void*)var, IPC_DEFAULT);
    if (var->session == NULL) return -1;

    ipc_session_set_callbacks(var->session, dm_mqtt_handle_recv_msg, NULL);
    dm_subscribe_all(var);
    ipc_session_start(var->session);
    return 0;
}

static int dm_init(dm_var_t *var)
{
    get_board_sn(var->sn_str);
    get_process_name(var->proc_name);

    dm_mqtt_client_init(var);

    var->module_slow_timer_fd = my_timer_create();
    if (var->module_slow_timer_fd > 0)
    {
        my_timer_set(var->module_slow_timer_fd, 5, 1000);
    }

    dy_syslog(LOG_INFO, "init done, board SN:%s", var->sn_str);

    return 0;
}

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

    memset(&var, 0, sizeof(var));

    dm_init(&var);
    dm_loop(&var);

    return 0;
}
