#include "dial.h"
#include <stdio.h>
#include <string>
#include <zlog.h>
#include "common/common_func.hpp"

extern zlog_category_t *zct;

Dial::Dial() {
    m_fd = 0;
    m_curState = CPIN;
    m_dial = 0;
    m_APN = 0;
}

Dial::~Dial() {}

int Dial::openPort(const char *pPort) {
    m_fd = config_uart(pPort, 115200);
    zlog_info(zct, "m_fd = %d\n", m_fd);
    return m_fd;
}

int Dial::parseData(Event event, const char *pData) {
    zlog_info(zct, "m_curState = %d,event = %d\n", m_curState, event);
    std::string signal;
    std::string ret;
    std::string str;
    int pos = 0;
    switch (event) {
        case Event_CPIN:
            if (!strncmp(pData, "READY", 5)) {
                m_curState = QCFGNET;
            } else if (!strncmp(pData, "NOT READY", 9)) {
                m_curState = CPIN;
                GlobalConfig::NetStatus = "\"LIMSRV\"";
            }
            break;
        case Event_QCFGNET:
        case Event_QCFGSMS: break;
        case Event_QICSGPAPN: {
            m_curState = QNETDEVCTL;
        } break;
        case Event_QENG:
            GlobalConfig::NetStatus = GetOneContent(pData, 1, ",");
            GlobalConfig::NetType = GetOneContent(pData, 2, ",");
            signal = GetOneContent(pData, 12, ",");
            GlobalConfig::NetSignal = atoi(signal.c_str());
            zlog_info(zct, "NetStatus = %s,NetSignal = %d", GlobalConfig::NetStatus.c_str(), GlobalConfig::NetSignal);
            break;
        case Event_QNETDEVCTL:
            zlog_info(zct, "m_curState Event_QNETDEVCTL = %d", m_curState);
            if (m_dial == 1) {
                m_curState = QNETDEVSTATUS;
            }
            break;
        case Event_QNETDEVSTATUS:
            ret = GetOneContent(pData, 3, ",");
            if (ret == "0" || ret == "")
                m_curState = QDCHPC;
            else
                m_curState = QNETDEVSTATUS;
            break;
        case Event_OK:
            if (m_curState == QNETDEVCTL && m_dial == 1) {
                m_dial = 0;
                m_curState = QNETDEVSTATUS;
            }
            if (m_curState == QCFGNET) {
                m_curState = QNETDEVCTL;
            }
            if (m_curState == QICSGPAPN && m_APN == 1) {
                m_APN = 0;
                m_curState = QNETDEVCTL;
            }

            break;
        case Event_ERROR:
            if (m_curState == CPIN && !strcmp(pData, "3")) {
                m_curState = CPIN;
                GlobalConfig::NetStatus = "\"LIMSRV\"";
            }
            if (m_curState == QNETDEVCTL) {
                m_curState = QNETDEVSTATUS;
            }
            break;
        case Event_TEMP:
            str = std::string(pData);
            pos = str.find("soc-thermal");
            if (pos > 0) {
                std::string socTmp = str.substr(pos + 14, 2);
                GlobalConfig::NR5GTemp = socTmp;
                zlog_info(zct, "NR5GTemp = %s", GlobalConfig::NR5GTemp.c_str());
            }

            break;
        default: break;
    }
    return 0;
}

int Dial::recvData() {
    char szbuffer[200] = {0x00};
    int offSize = 0;
    int timeoutflag = 0;
    while (1) {
        char buff[1024] = {0x00};

        int ret = read_data(m_fd, buff, 1024, 10);
        if (ret <= 0) {
            timeoutflag++;
            if (timeoutflag > 5) {
                timeoutflag = 0;
                const char *strQENG = "+QENG: ";
                const char *strQNETDEVCTL = "+QNETDEVCTL: ";
                const char *strQICSGP = "+QICSGP: ";
                const char *strQNETDEVSTATUS = "+QNETDEVSTATUS: ";
                const char *strQCFG = "+QCFG: ";
                const char *strCPIN = "+CPIN: ";
                const char *strERROR = "+CME ERROR: ";
                const char *strQTEMP = "+QTEMP: ";
                const char *strOK = "OK";
                char data[128] = {0};
                char *pdata = strstr((char *)szbuffer, strQENG);
                if (pdata) {
                    strncpy(data, pdata + 7, sizeof(data));
                    zlog_info(zct, "strQENG = %s", data);
                    parseData(Event_QENG, data);
                }
                pdata = strstr((char *)szbuffer, strQNETDEVCTL);
                if (pdata) {
                    strncpy(data, pdata + 13, sizeof(data));
                    zlog_info(zct, "strQNETDEVCTL = %s", data);
                    parseData(Event_QNETDEVCTL, data);
                }
                pdata = strstr((char *)szbuffer, strQICSGP);
                if (pdata) {
                    strncpy(data, pdata + 9, sizeof(data));
                    zlog_info(zct, "strQICSGP = %s", data);
                    parseData(Event_QICSGPAPN, data);
                }
                pdata = strstr((char *)szbuffer, strQNETDEVSTATUS);
                if (pdata) {
                    strncpy(data, pdata + 16, sizeof(data));
                    zlog_info(zct, "strQNETDEVSTATUS = %s", data);
                    parseData(Event_QNETDEVSTATUS, data);
                }
                pdata = strstr((char *)szbuffer, strQCFG);
                if (pdata) {
                    strncpy(data, pdata + 7, sizeof(data));
                    zlog_info(zct, "strQCFG = %s", data);
                    parseData(Event_QCFGNET, data);
                }
                pdata = strstr((char *)szbuffer, strCPIN);
                if (pdata) {
                    strncpy(data, pdata + 7, sizeof(data));
                    zlog_info(zct, "strCPIN = %s", data);
                    parseData(Event_CPIN, data);
                }
                pdata = strstr((char *)szbuffer, strQTEMP);
                if (pdata) {
                    strncpy(data, pdata + 8, sizeof(data));
                    zlog_info(zct, "strQTEMP = %s", data);
                    parseData(Event_TEMP, data);
                }
                pdata = strstr((char *)szbuffer, strERROR);
                if (pdata) {
                    strncpy(data, pdata + 12, sizeof(data));
                    zlog_info(zct, "strERROR = %s", data);
                    parseData(Event_ERROR, data);
                }
                pdata = strstr((char *)szbuffer, strOK);
                if (pdata) {
                    parseData(Event_OK, data);
                }
                memset(szbuffer, 0x00, sizeof(szbuffer));
                offSize = 0;
            }
            mssleep(100);
        } else if (ret > 0) {
            zlog_info(zct, "ret = %d,buff = %s", ret, buff);
            memcpy(szbuffer + offSize, buff, ret);
            offSize = offSize + ret;
            zlog_info(zct, "szbuffer = %s", szbuffer);
            continue;
        }
        mssleep(500000);
    }
}

int Dial::queryPin() { return write_data(m_fd, (char *)std::string("AT+CPIN?\r\n").c_str(), 12); }

int Dial::configNet() { return write_data(m_fd, (char *)std::string("AT+QCFG=\"NAT\"\r\n").c_str(), 19); }

int Dial::configApn() {
    m_APN = 1;
    std::string strAPN = ReadStrByOpt(SERVERCONFIG, "Server", "APN");
    char szCmd[100] = {0x00};
    sprintf(szCmd, "AT+QICSGP=1,1,\"%s\",\"\",\"\",1\r\n", strAPN.c_str());
    int iRet = write_data(m_fd, szCmd, strlen(strAPN.c_str()) + 34);
    zlog_info(zct, "configApn = %d,data = %s\n", iRet, szCmd);
    return 0;
}

int Dial::getCsq() { return write_data(m_fd, (char *)std::string("AT+QENG=\"servingcell\"\r\n").c_str(), 27); }

int Dial::getTemp() { return write_data(m_fd, (char *)std::string("AT+QTEMP\r\n").c_str(), 12); }

int Dial::conncectUSB() {
    int iRet = write_data(m_fd, (char *)std::string("AT+QNETDEVCTL=1,1,1\r\n").c_str(), 23);
    zlog_info(zct, "conncectUSB = %d\n", iRet);
    return iRet;
}

int Dial::dial5G() {
    while (1) {
        if (m_curState == CPIN) {
            queryPin();
        } else if (m_curState == QCFGNET) {
            configNet();
        } else if (m_curState == QICSGPAPN) {
            configApn();
        } else if (m_curState == QENG) {
            getCsq();
        } else if (m_curState == QNETDEVCTL) {
            conncectUSB();
            m_dial = 1;
        } else if (m_curState == QNETDEVSTATUS) {
            write_data(m_fd, (char *)std::string("AT+QNETDEVSTATUS=1\r\n").c_str(), 22);
        } else if (m_curState == QDCHPC) {
            configdhcp();
            m_curState = QENG;
        } else {
            // TODO: show valid log info
        }
        sleep(5);
        getTemp();
        sleep(15);
    }
    return 0;
}

int Dial::configims() {
    write_data(m_fd, (char *)std::string("AT+QCFG=\"ims\",0\r\n").c_str(), 21);
    return 0;
}

int Dial::configdhcp() {
    system("busybox udhcpc -f -n -q -t 5 -i usb0");
    return 0;
}

int Dial::setState() {
    m_curState = CPIN;
    return 0;
}

int Dial::closePort() {
    close(m_fd);
    return 0;
}
