#include <signal.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <boost/thread.hpp>
#include <zlog.h>
#include "platform/platform_init.hpp"
#include "common/common_func.hpp"
#include "common/global.hpp"
#include "threadfunc/thread_func.hpp"
#include "utility/secure.hpp"
#include "utility/aes.h"
#include "dbaccess/sql_db.hpp"
#include "uart/uart.hpp"
#include "minilzo/minilzo.h"

extern std::vector<RecvData> g_VecWaveDataX;
extern std::vector<RecvData> g_VecWaveDataY;
extern std::vector<RecvData> g_VecWaveDataZ;
extern std::vector<RecvData> g_VecWaveDataVolX;
extern std::vector<RecvData> g_VecWaveDataVolY;
extern std::vector<RecvData> g_VecWaveDataVolZ;
zlog_category_t *zct = NULL;
zlog_category_t *zbt = NULL;

int main(int argc, char *argv[]) {
    int rc = zlog_init("/opt/configenv/wlg.conf");
    if (rc) {
        printf("init failed\n");
        return -1;
    }

    zct = zlog_get_category("wlg");
    zbt = zlog_get_category("cfg");
    if (!zct || !zbt) {
        printf("get category fail\n");
        zlog_fini();
        return -2;
    }

    zlog_info(zbt, " Firmware compile time:%s %s,version %s", __DATE__, __TIME__, GlobalConfig::Version.c_str());
    zlog_info(zbt, "####CIDNSOFT start####");       
    GlobalConfig::Version += " " + std::string(__DATE__) ;

    g_VecWaveDataX.reserve(1000);
    g_VecWaveDataY.reserve(1000);
    g_VecWaveDataZ.reserve(1500);
    g_VecWaveDataVolX.reserve(1000);
    g_VecWaveDataVolY.reserve(1000);
    g_VecWaveDataVolZ.reserve(1500);
    boost::thread::attributes attrs;
    attrs.set_stack_size(1024 * 1024);

    PlatformInit::Init();

    sqlite_db_ctrl::instance().InintGateway();
    char localtimestamp[32] = { 0 };
    char insertSql[128] = { 0 };
    GetTimeNet(localtimestamp, 1);
    memset(insertSql,0,sizeof(insertSql));
    sprintf(insertSql, " '3','CIDNSOFT start','%s'",localtimestamp);
    sqlite_db_ctrl::instance().InsertData("t_process_info", insertSql);

    uart_inst::instance().InitZigbeeHW();
    // UDP，接收客户端发来的组播消息，用于外接 QT 专家系统，屏蔽之
    boost::thread searchT(SearchThread);
    searchT.detach();

    // 串口处理线程,用于与 ZigBee 模块通信，通过ZigBee无线通信技术与无线传感器通信
    boost::thread uartReadTh(UartStart);
    uartReadTh.detach();

    boost::thread uartTestReadTh(TestUart);
    uartReadTh.detach();

    // boost::thread InitModuleReadTh(InitModule);
    // InitModuleReadTh.detach();

    InitModule();

    // 休眠2秒，等待串口线程初始化完毕
    sleep(2);

    // 串口数据处理,读取传感器原始波形数据
    boost::thread uartWaveReadTh(UartStartWave);
    uartWaveReadTh.detach();


#ifdef NR5G_MODULE
    print_info("NR5G_MODULE \n");
    // 5G
    boost::thread startCSQ(GetCSQ);
    startCSQ.detach();
#ifndef NR5G_MEIGE
    boost::thread startDial(Dial5G);
    startDial.detach();
#endif
#endif

#ifdef Q4G_MODULE
    boost::thread startCSQ(GetCSQ);
    startCSQ.detach();
    zlog_info(zbt,"4G_MODULE");

#endif
#ifdef WIFI_MODULE
    print_info("WiFi_MODULE \n");
#endif

    //通过UDP接收数据
    boost::thread StartConnectSys(attrs, StartUdpSys);
    StartConnectSys.detach();

    //循环检测线程
    boost::thread normalCheckThread(attrs, CheckThread);
    normalCheckThread.detach();

    //启动cgi server
    boost::thread startTcpCgi(attrs, StartCgiServer);
    startTcpCgi.detach();

    sleep(5);
    uart_inst::instance().ZigbeeParameterConfig();
    sleep(1);
    uart_inst::instance().UpdateZigbeeInfoCtrl();

    //启动 mqtt客户端
    boost::thread startMqtt(StartMqttClient);
    startMqtt.detach();

    //启动 mqtt 心跳
    boost::thread startHeart(HeartRep);
    startHeart.detach();

    boost::thread DiskCheck(attrs, DiskSpaceCheck);
    DiskCheck.detach();

    if (lzo_init() != LZO_E_OK) {
        zlog_error(zbt, "internal error - lzo_init() failed !!!");
        zlog_error(zbt, "(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)");
    }
    //启动CMT server
    boost::thread startTcpCmt(attrs, StartCMTServer);
    startTcpCmt.detach();
    
    int fd = OpenWatchDog();
    int count = 0;
    while (GlobalConfig::QuitFlag_G) {
        WriteWatchDog(fd);
        sleep(20);
        if (GlobalConfig::threadStatus == 0) {
            count++;
        } else if (GlobalConfig::threadStatus == 1) {
            GlobalConfig::threadStatus = 0;
            count = 0;
        }
        if (count >= 30) {
            zlog_error(zbt, "===========threadStatus ========failed");
            char localtimestamp[32] = { 0 };
            GetTimeNet(localtimestamp, 1);
            memset(insertSql,0,sizeof(insertSql));
            sprintf(insertSql, " '1','CheckThread failed','%s'",localtimestamp);
            sqlite_db_ctrl::instance().InsertData("t_process_info", insertSql);
            break;
        }
    }
    return 0;
}
