#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <jni.h>
#include <unistd.h>
#include "gt.h"
#include "gterror.h"
#include "gtstruct.h"
#include "gttoolkitext.h"
#include "gtsystem.h"
#include "gttrading.h"
#include "gtfiletransfer.h"
#include "gtmem.h"

GtSystem *GtSystem::_instance = NULL;

GtSystem::GtSystem() {

}

GtSystem::~GtSystem() {

}

GtSystem *GtSystem::instance() {
    if (_instance == NULL) {
        _instance = new GtSystem();
    }
    return _instance;
}

/************************************************************
*功能：创建默认的终端配置数据
*输入：无
*输出：terminal=终端配置数据
*返回：无
 * 宁夏V95： 10.13.0.17  6400  6470  64010230
 * 宁夏V11:  10.7.0.60   6400  6470  64010382
 *
*/
void GtSystem::defaultTerminalConfig(stTerminal *terminal) {
    int i = 0;
    memset(terminal, 0, sizeof(stTerminal));
    strcpy(terminal->strTerminalID, "64010382");
    strcpy(terminal->strTerminalCert, "");
    terminal->ucCommLineNo = 0;
    terminal->ucTerminalAuthType = 1;
    for (i = 0; i < MAX_COMM_LINE_SIZE; i++) {
        terminal->commAttr[i].ucType = 5;
        terminal->commAttr[i].ucLineID = 0;
        terminal->commAttr[i].ucValid = 1;
        strcpy(terminal->commAttr[i].strName, "局域网");
        strcpy(terminal->commAttr[i].strIP1, "10.7.0.60");
        strcpy(terminal->commAttr[i].strIP2, "10.7.0.60");
        strcpy(terminal->commAttr[i].strIP3, "");
        strcpy(terminal->commAttr[i].strIP4, "");

        terminal->commAttr[i].unPort1 = 6400;
        terminal->commAttr[i].unPort2 = 6470;
        terminal->commAttr[i].unPort3 = 0;
        terminal->commAttr[i].unPort4 = 0;
    }
}

/************************************************************
*功能：读取终端配置文件，如果文件不存在则创建默认终端配置文件
*输入：无
*输出：terminal=终端配置数据
*返回：!=0错误
*/
int GtSystem::readTerminalConfig(stTerminal *terminal) {
    int result = 0;
    char path[512];
    stTerminal term;

    memset(path, 0, sizeof(path));
    Gt::instance()->getTerminalCfgFile(path);
    memset(&term, 0, sizeof(stTerminal));
    result = GtToolkitExt::isFileExist(path);
    if (result != 0) {
        defaultTerminalConfig(&term);
        result = GtToolkitExt::writeSyncFile(path, &term, sizeof(stTerminal));
        if (result != 0) {
            return result;
        }
    } else {
        result = GtToolkitExt::readFile(path, &term, sizeof(stTerminal));
        if (result != 0) {
            return result;
        }
    }
    memcpy(terminal, &term, sizeof(stTerminal));
    return 0;
}

/************************************************************
*功能：写入终端配置文件
*输入：terminal=终端配置数据
*输出：无
*返回：!=0错误
*/
int GtSystem::writeTerminalConfig(stTerminal *terminal) {
    int result = 0;
    char path[512];

    memset(path, 0, sizeof(path));
    Gt::instance()->getTerminalCfgFile(path);
    result = GtToolkitExt::writeSyncFile(path, terminal, sizeof(stTerminal));
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "写入磁盘同步文件错误<%d>", result);
        return result;
    }
    return 0;
}

/************************************************************
*功能：保存终端配置文件，同时更新终端配置内存数据
*输入：terminal=终端配置数据
*输出：无
*返回：!=0错误
*/
int GtSystem::saveTerminalConfig(stTerminal *terminal) {
    int result = 0;

    result = writeTerminalConfig(terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "写入终端配置文件错误<%d>", result);
        return result;
    }
    result = GtMem::instance()->setMemTerminal(terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "写入终端配置内存数据错误<%d>", result);
        return result;
    }
    GtToolkitExt::logInfo(__FILE__, __LINE__, "save success strTerminalCert = %s, ip = %s",
                          terminal->strTerminalCert, terminal->commAttr[0].strIP1);
    return 0;
}

/************************************************************
*功能：初始化系统
*输入：无
*输出：无
*返回：!=0错误
*/
int GtSystem::initSystem() {
    int result = 0;
    stTerminal terminal;

    //读取终端配置
    memset(&terminal, 0, sizeof(stTerminal));
    result = readTerminalConfig(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "读取终端配置文件错误<%d>", result);
        return result;
    }
    //同步数据到内存
    result = GtMem::instance()->setMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "写入终端配置内存数据错误<%d>", result);
        return result;
    }
    return 0;
}

/************************************************************
*功能：登录流程
*输入：无
*输出：无
*返回：!=0错误
*/
int GtSystem::loginProcess(JNIEnv *env, int lineNo, int userName, char *password) {
    stRuntime runtime;
    int result = 0;
    time_t ltime = 0;

    memset(&runtime, 0, sizeof(stRuntime));
    result = GtMem::instance()->getMemRuntime(&runtime);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "读取终端运行内存数据错误<%d>", result);
        return result;
    }
    if (userName >= 0) {
        runtime.ucUserID = userName;
        memset(runtime.strUserPassword, 0, sizeof(runtime.strUserPassword));
        strcpy(runtime.strUserPassword, password);
        runtime.ucUserAuthType = 1;
        result = GtMem::instance()->setMemRuntime(&runtime);
        if (result != 0) {
            GtToolkitExt::logError(__FILE__, __LINE__, "保存终端运行内存数据错误<%d>", result);
            return result;
        }
    }
    //连接服务器    
    result = GtTrading::instance()->t100000ConnectServer(100000);
    if (result != 0) {
        return result;
    }

    //取通讯秘钥
    result = GtTrading::instance()->t101000CommEncryptKey(101000);
    if (result != 0) {
        return result;
    }
    //登录
    result = GtTrading::instance()->t101001TerminalLogin(101001);
    if (result != 0) {
        return result;
    }
    //同步服务器时间
    result = GtTrading::instance()->t101025GetServerTime(101025, &ltime);
    if (result != 0) {
        return result;
    }
    //取控制参数
    result = GtTrading::instance()->t101027GetControlInfo(101027);
    if (result != 0) {
        return result;
    }
    //result = autoDownload(env, (char *)"1.0.0");
//    if (result != 0) {
//        return result;
//    }
    return 0;
}

/************************************************************
*功能：登录过程强制下载升级
*输入：无
*输出：无
*返回：!=0错误
*/
int GtSystem::autoDownload(JNIEnv *env, char *localVer) {
    stCtrlInfo ctrlInfo;
    stTerminal terminal;
    int result = 0;

    memset(&ctrlInfo, 0, sizeof(stCtrlInfo));
    result = GtMem::instance()->getMemCtrlInfo(&ctrlInfo);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "读取控制参数内存数据错误<%d>", result);
        return result;
    }
    if (ctrlInfo.ucFileDownload == 0) {
        return 0;
    }
    memset(&terminal, 0, sizeof(stTerminal));
    result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "读取终端配置内存数据错误<%d>", result);
        return result;
    }
    GtFileTransfer *fileTrans = new GtFileTransfer();
    result = fileTrans->fileServerLink(terminal.commAttr[terminal.ucCommLineNo].strIP2,
                                       terminal.commAttr[terminal.ucCommLineNo].unPort2);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "连接文件服务器错误<%d>", result);
        return result;
    }
    if ((ctrlInfo.ucFileDownload & 0x80) == 0x80) {
        result = downloadApp(env, fileTrans, localVer);
        if (result != 0) {
            fileTrans->closeFileServerLink();
            delete fileTrans;
            fileTrans = NULL;
            return result;
        }
    }
    if ((ctrlInfo.ucFileDownload & 0x40) == 0x40) {

    }
    if ((ctrlInfo.ucFileDownload & 0x08) == 0x08) {

    }
    return 0;
}

/************************************************************
*功能：下载APP升级程序，并自动安装
*输入：env=JVM环境
*输入：terminal=终端配置数据
*输入：ver=本地版本
*输出：无
*返回：!=0错误
*/
int GtSystem::downloadApp(JNIEnv *env, GtFileTransfer *fileTrans, char *ver) {
    int result = 0;
    char serverVerFile[256];
    char localVerFile[256];
    char tmpBuf[128];
    char strBuf[128];

    if (env == NULL || fileTrans == NULL || ver == NULL) {
        return GtError::ERROR_INVALID_FUNC_PARAM;
    }
    //下载服务器版本文件
    memset(serverVerFile, 0, sizeof(serverVerFile));
    strcpy(serverVerFile, "app/version");
    memset(localVerFile, 0, sizeof(localVerFile));
    memset(tmpBuf, 0, sizeof(tmpBuf));
    Gt::instance()->getDownloadPath(tmpBuf);
    sprintf(localVerFile, "%s/version", tmpBuf);
    result = fileTrans->downloadFile(env, serverVerFile, localVerFile, 0);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "版本文件[%s]下载错误<%d>", serverVerFile, result);
        return result;
    }
    //版本比较
    memset(strBuf, 0, sizeof(strBuf));
    result = GtToolkitExt::readAttrFromFile(localVerFile, "AppVersion=", strBuf);
    if (result != 0) {
        return result;
    }
    strcat(strBuf, ".");
    memset(tmpBuf, 0, sizeof(tmpBuf));
    sprintf(tmpBuf, "%s.", ver);
    if (compareAppVersion(tmpBuf, strBuf) != 0) {
        GtTrading::instance()->t101023AppUpgradeCompleted(101023);
        return 0;
    }
    //下载升级包
    memset(serverVerFile, 0, sizeof(serverVerFile));
    strcpy(serverVerFile, "app/app-release.apk");
    memset(localVerFile, 0, sizeof(localVerFile));
    memset(tmpBuf, 0, sizeof(tmpBuf));
    Gt::instance()->getDownloadPath(tmpBuf);
    sprintf(localVerFile, "%s/app-release.apk", tmpBuf);
    result = fileTrans->downloadFile(env, serverVerFile, localVerFile, 1);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "升级包文件[%s]下载错误<%d>", serverVerFile, result);
        return result;
    }
#if 0
    //调用java接口静默升级
    jclass classObj = env->FindClass("com/genlot/terminal/application/GtApplication");
    if(classObj == NULL)
    {
        GtUtilsExt::logError(__FILE__, __LINE__, "[%d]jni数据转换错误", GtError::ERR_INVALID_VALUE);
        return GtError::ERR_INVALID_VALUE;
    }
    jmethodID methodID = env->GetStaticMethodID(classObj, "getInstance", "()Lcom/genlot/terminal/application/GtApplication;");
    if(methodID == NULL)
    {
        GtUtilsExt::logError(__FILE__, __LINE__, "[%d]jni数据转换错误", GtError::ERR_INVALID_VALUE);
        return GtError::ERR_INVALID_VALUE;
    }
    jobject instance = env->CallStaticObjectMethod(classObj, methodID);
    if(instance == NULL)
    {
        GtUtilsExt::logError(__FILE__, __LINE__, "[%d]jni数据转换错误", GtError::ERR_INVALID_VALUE);
        return GtError::ERR_INVALID_VALUE;
    }
    methodID = env->GetMethodID(classObj, "installApp", "(Ljava/lang/String;)I");
    if(methodID == NULL)
    {
        GtUtilsExt::logError(__FILE__, __LINE__, "[%d]jni数据转换错误", GtError::ERR_INVALID_VALUE);
        return GtError::ERR_INVALID_VALUE;
    }
    jstring str = env->NewStringUTF(localVerFile);
    result = env->CallIntMethod(instance, methodID, str);
    env->DeleteLocalRef(str);
    env->DeleteLocalRef(instance);
    env->DeleteLocalRef(classObj);
    if(result != 0)
    {
        return GtError::ERR_AUTO_UPGRADE;
    }
#endif
    return 0;
}

/************************************************************
*功能：比较服务器与本地APP版本
*输入：localVer=本地APP版本号
*输出：serverVer=服务器APP版本号
*返回：=0服务器版本更高，!=0本地版本更高
*/
int GtSystem::compareAppVersion(char *localVer, char *serverVer) {
    char tmpBuf[128];
    int mV = 0;
    int sV = 0;
    int tV = 0;
    int result = 0;

    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtToolkitExt::parseNChar(serverVer, tmpBuf, sizeof(tmpBuf), '.', 1);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]服务器主版本解析错误", result);
        return result;
    }
    mV = atoi(tmpBuf);
    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtToolkitExt::parseNChar(localVer, tmpBuf, sizeof(tmpBuf), '.', 1);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]本地主版本解析错误", result);
        return result;
    }
    if (mV > atoi(tmpBuf)) {
        return 0;
    }
    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtToolkitExt::parseNChar(serverVer, tmpBuf, sizeof(tmpBuf), '.', 2);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]服务器次版本解析错误", result);
        return result;
    }
    sV = atoi(tmpBuf);
    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtToolkitExt::parseNChar(localVer, tmpBuf, sizeof(tmpBuf), '.', 2);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]本地次版本解析错误", result);
        return result;
    }
    if (sV > atoi(tmpBuf)) {
        return 0;
    }
    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtToolkitExt::parseNChar(serverVer, tmpBuf, sizeof(tmpBuf), '.', 3);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]服务器小版本解析错误", result);
        return result;
    }
    tV = atoi(tmpBuf);
    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtToolkitExt::parseNChar(localVer, tmpBuf, sizeof(tmpBuf), '.', 3);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]本地小版本解析错误", result);
        return result;
    }
    if (tV > atoi(tmpBuf)) {
        return 0;
    }
    return -1;
}

/************************************************************
*功能：首次启动应用，生成配置文件
*输入：无
*输出：无
*返回：!=0错误
*/
int GtSystem::firstLoad() {
    char path[512];
    char tmpBuf[64];
    int length = 0;
    int result = 0;

    memset(path, 0, sizeof(path));
    Gt::instance()->getFirstLoadCfgFile(path);
    memset(tmpBuf, 0, sizeof(tmpBuf));
    length = sprintf(tmpBuf, "%s", "firstload");
    result = GtToolkitExt::writeSyncFile(path, tmpBuf, length);
    return result;
}

/************************************************************
*功能：是否首次启动应用
*输入：无
*输出：无
*返回：true首次启动，false非首次启动
*/
bool GtSystem::isFirstLoad() {
    char path[512];
    int result = 0;

    memset(path, 0, sizeof(path));
    Gt::instance()->getFirstLoadCfgFile(path);
    result = GtToolkitExt::isFileExist(path);
    if (result != 0) {
        return true;
    } else {
        return false;
    }
}

