#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "gtmatchkey.h"
#include "gttoolkitext.h"
#include "gt.h"
#include "gterror.h"
#include "gtmem.h"
#include "gtgateway.h"
#include "gtsender.h"
#include "gtsystem.h"
#include "gtencrypt.h"
#include "gtfiletransfer.h"

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env = nullptr;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    return JNI_VERSION_1_6;
}

/*================Native framework 入口================*/
extern "C"
JNIEXPORT jboolean JNICALL Java_com_genlot_nativesdk_SystemNI_initNative
        (JNIEnv *env, jclass objClass, jobject contextObj, jstring appPath) {
    char *tmpStr = nullptr;

    //禁止非授权用户使用
    if (!GtMatchKey::matchKey(env, contextObj)) {
        return static_cast<jboolean>(false);
    }
    tmpStr = (char *) (env->GetStringUTFChars(appPath, 0));
    if (tmpStr == nullptr) {
        return static_cast<jboolean>(false);
    }
    //设置路径
    Gt::instance()->setAppPath(tmpStr);
    //初始化系统
    GtSystem::instance()->initSystem();
    return static_cast<jboolean>(true);
}



/*================GtNetwork模块接口================*/
extern "C" JNIEXPORT jboolean JNICALL Java_com_genlot_nativesdk_SystemNI_startGateway
        (JNIEnv *env, jclass objClass) {
    //禁止非授权用户使用
    if (!GtMatchKey::isMatched()) {
        return static_cast<jboolean>(false);
    }
    GtGateway::instance()->start();
    return static_cast<jboolean>(true);
}

extern "C" JNIEXPORT jboolean JNICALL Java_com_genlot_nativesdk_SystemNI_stopGateway
        (JNIEnv *env, jclass objClass) {
    //禁止非授权用户使用
    if (!GtMatchKey::isMatched()) {
        return static_cast<jboolean>(false);
    }
    GtGateway::instance()->stop();
    return static_cast<jboolean>(true);
}

extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_callGateway
        (JNIEnv *env, jclass objClass, jint tradingCode, jbyteArray inData, jint inSize,
         jbyteArray outData, jintArray outSize) {
    unsigned char tmpBuf[10240];
    int size[2] = {0};
    int result = 0;
    int outLen = 0;

    //禁止非授权用户使用
    if (!GtMatchKey::isMatched()) {
        return GtError::ERROR_OTHER;
    }
    jbyte *bytes = env->GetByteArrayElements(inData, 0);
    if (bytes == NULL) {
        return -1;
    }
    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtSender::sendMessage(tradingCode, (unsigned char *) bytes, inSize, tmpBuf, &outLen);
    env->SetByteArrayRegion(outData, 0, outLen, (jbyte *) tmpBuf);
    size[0] = outLen;
    env->SetIntArrayRegion(outSize, 0, 1, (jint *) size);
    return result;
}

extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_loginProcess
        (JNIEnv *env, jclass objClass, jint lineNo, jint user, jstring password) {
    char *tmpStr = NULL;
    //禁止非授权用户使用
    if (!GtMatchKey::isMatched()) {
        return GtError::ERROR_OTHER;
    }
    tmpStr = (char *) (env->GetStringUTFChars(password, 0));
    if (tmpStr == NULL) {
        return false;
    }
    return GtSystem::instance()->loginProcess(env, lineNo, user, tmpStr);
}

extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_getGameSize
        (JNIEnv *env, jclass objClass) {
    stGameRuntime gameRuntime;
    memset(&gameRuntime, 0, sizeof(stGameRuntime));
    int result = GtMem::instance()->getMemGameRuntime(&gameRuntime);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取游戏内存信息错误<%d>", result);
        return result;
    }
    return gameRuntime.unGameCount;
}

extern "C"
JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_getGameID
        (JNIEnv *env, jclass objClass, jintArray gameID) {
    stGameRuntime gameRuntime;
    memset(&gameRuntime, 0, sizeof(stGameRuntime));
    int result = GtMem::instance()->getMemGameRuntime(&gameRuntime);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取游戏内存信息错误<%d>", result);
        return result;
    }
    int tmpBuf[256];
    for (int i = 0; i < gameRuntime.unGameCount; i++) {
        tmpBuf[i] = gameRuntime.gameAttr[i].unGameID;
    }
    env->SetIntArrayRegion(gameID, 0, gameRuntime.unGameCount, (jint *) tmpBuf);
    return 0;
}

extern "C"
JNIEXPORT jdouble JNICALL
Java_com_genlot_nativesdk_SystemNI_getProtectMoney(JNIEnv *env, jclass type) {
    stCtrlInfo ctrlInfo;
    memset(&ctrlInfo, 0, sizeof(stCtrlInfo));
    int result = GtMem::instance() -> getMemCtrlInfo(&ctrlInfo);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "读取控制配置内存数据错误<%d>", result);
        return -1;
    }
    return ctrlInfo.dTicketCtrlMoney;
}

/*================GtFileTransfer模块接口================*/
extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_downloadFile
        (JNIEnv *env, jclass obj, jstring serverFile, jstring localFile, jint isBP) {
    stTerminal terminal;
    char fileName[512];
    char fileName2[512];
    int result = 0;

    memset(fileName, 0, sizeof(fileName));
    result = GtToolkitExt::jString2Char(env, serverFile, fileName, sizeof(fileName));
    if (result != 0) {
        return result;
    }
    memset(fileName2, 0, sizeof(fileName2));
    result = GtToolkitExt::jString2Char(env, localFile, fileName2, sizeof(fileName2));
    if (result != 0) {
        return result;
    }
    memset(&terminal, 0, sizeof(stTerminal));
    result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端配置内存信息错误<%d>", result);
        return result;
    }
    GtToolkitExt::logInfo(__FILE__, __LINE__, "连接文件服务器[%s:%d]",
                          terminal.commAttr[terminal.ucCommLineNo].strIP2,
                          terminal.commAttr[terminal.ucCommLineNo].unPort2);
    GtFileTransfer *fileTransfer = new GtFileTransfer();
    result = fileTransfer->fileServerLink(terminal.commAttr[terminal.ucCommLineNo].strIP2,
                                          terminal.commAttr[terminal.ucCommLineNo].unPort2);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "连接文件服务器错误<%d>", result);
        fileTransfer->closeFileServerLink();
        delete fileTransfer;
        return result;
    }
    result = fileTransfer->downloadFile(env, fileName, fileName2, isBP);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "文件下载错误<%d>", result);
        fileTransfer->closeFileServerLink();
        delete fileTransfer;
        return result;
    }
    fileTransfer->closeFileServerLink();
    delete fileTransfer;
    return 0;
}

extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_uploadFile
        (JNIEnv *env, jclass obj, jstring serverFile, jstring localFile) {
    stTerminal terminal;
    char fileName[512];
    char fileName2[512];
    int result = 0;

    memset(fileName, 0, sizeof(fileName));
    result = GtToolkitExt::jString2Char(env, serverFile, fileName, sizeof(fileName));
    if (result != 0) {
        return result;
    }
    memset(fileName2, 0, sizeof(fileName2));
    result = GtToolkitExt::jString2Char(env, localFile, fileName2, sizeof(fileName2));
    if (result != 0) {
        return result;
    }
    memset(&terminal, 0, sizeof(stTerminal));
    result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]获取终端配置内存信息错误", result);
        return result;
    }
    GtToolkitExt::logInfo(__FILE__, __LINE__, "连接文件服务器[%s:%d]",
                          terminal.commAttr[terminal.ucCommLineNo].strIP2,
                          terminal.commAttr[terminal.ucCommLineNo].unPort2);
    GtFileTransfer *fileTransfer = new GtFileTransfer();
    result = fileTransfer->fileServerLink(terminal.commAttr[terminal.ucCommLineNo].strIP2,
                                          terminal.commAttr[terminal.ucCommLineNo].unPort2);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]连接文件服务器错误", result);
        fileTransfer->closeFileServerLink();
        delete fileTransfer;
        fileTransfer = nullptr;
        return result;
    }
    result = fileTransfer->uploadFile(env, fileName, fileName2);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "[%d]文件上传错误", result);
        fileTransfer->closeFileServerLink();
        delete fileTransfer;
        fileTransfer = nullptr;
        return result;
    }
    fileTransfer->closeFileServerLink();
    delete fileTransfer;
    fileTransfer = nullptr;
    return 0;
}

extern "C" JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_getResourcePath
        (JNIEnv *env, jclass obj) {
    char fileName[512];
    memset(fileName, 0, sizeof(fileName));
    Gt::instance()->getResourcePath(fileName);
    return env->NewStringUTF(fileName);
}

extern "C"
JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_getDownloadPath
        (JNIEnv *env, jclass obj) {
    char fileName[512];
    memset(fileName, 0, sizeof(fileName));
    Gt::instance()->getDownloadPath(fileName);
    return env->NewStringUTF(fileName);
}

extern "C" JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_getLogPath
        (JNIEnv *env, jclass obj) {
    char fileName[512];
    memset(fileName, 0, sizeof(fileName));
    Gt::instance()->getLogPath(fileName);
    return env->NewStringUTF(fileName);
}

extern "C" JNIEXPORT void JNICALL Java_com_genlot_nativesdk_SystemNI_writeErrorLogFile
        (JNIEnv *env, jclass obj, jstring tag, jstring data) {
    int result = 0;
    char fileN[512];
    char tagBuf[128];
    char tmpBuf[2048];

    memset(fileN, 0, sizeof(fileN));
    Gt::instance()->getErrorLogFile(fileN);
    memset(tagBuf, 0, sizeof(tagBuf));
    result = GtToolkitExt::jString2Char(env, tag, tagBuf, sizeof(tagBuf));
    if (result != 0) {
        return;
    }
    memset(tmpBuf, 0, sizeof(tmpBuf));
    result = GtToolkitExt::jString2Char(env, data, tmpBuf, sizeof(tmpBuf));
    if (result != 0) {
        return;
    }
    GtToolkitExt::limitFileSize(fileN);
    GtToolkitExt::errorLogFile(fileN, tagBuf, tmpBuf);
}

extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_readLastTicket
        (JNIEnv *env, jclass obj, jobject ticket) {
    stLastTicket lastTicket;
    memset(&lastTicket, 0, sizeof(stLastTicket));
    if (GtSender::readLastTicketFile(&lastTicket) != 0) {
        return 0;
    }

    //C层数据转换为Java层数据
    jclass objClass = env->GetObjectClass(ticket);
    if (objClass == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return GtError::ERROR_INVALID_VALUE;
    }
    //设置游戏ID
    jfieldID fieldID = env->GetFieldID(objClass, "mGameID", "I");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return GtError::ERROR_INVALID_VALUE;
    }
    env->SetIntField(ticket, fieldID, lastTicket.unGameID);
    //设置游戏期号
    fieldID = env->GetFieldID(objClass, "mGameIssue", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return GtError::ERROR_INVALID_VALUE;
    }
    env->SetLongField(ticket, fieldID, lastTicket.ulIssue);
    //设置票流水号
    fieldID = env->GetFieldID(objClass, "mTicketSN", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return GtError::ERROR_INVALID_VALUE;
    }
    env->SetLongField(ticket, fieldID, lastTicket.ulTicketSN);
    //设置终端ID
    fieldID = env->GetFieldID(objClass, "mTerminalID", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return GtError::ERROR_INVALID_VALUE;
    }
    env->SetLongField(ticket, fieldID, lastTicket.ulTerminalID);
    //设置key
    fieldID = env->GetFieldID(objClass, "mFeatureKey", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return GtError::ERROR_INVALID_VALUE;
    }
    env->SetLongField(ticket, fieldID, lastTicket.ulKey);
    //设置前端流水号
    fieldID = env->GetFieldID(objClass, "mFrontSN", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return GtError::ERROR_INVALID_VALUE;
    }
    env->SetLongField(ticket, fieldID, lastTicket.ulFrontSN);
    env->DeleteLocalRef(objClass);
    return 0;
}

extern "C" JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_rc4EncryptData
        (JNIEnv *env, jclass obj, jstring srcStringData) {
    unsigned char key[32] = {
            0x02, 0x90, 0x52, 0xea, 0x9f, 0xff, 0xa7, 0x9d,
            0x18, 0x24, 0xe3, 0x8b, 0xdd, 0x1a, 0x14, 0xa5,
            0xed, 0xe9, 0x97, 0xb0, 0xca, 0xf2, 0xec, 0x39,
            0x81, 0x10, 0xd7, 0x9d, 0x9e, 0xba, 0x38, 0xbb
    };

    int encryptDataBufLen = 0;

    unsigned char encryptDataBuf[1024];
    memset(encryptDataBuf, 0, sizeof(encryptDataBuf));

    char tmpBuf[1024];
    memset(tmpBuf, 0, sizeof(tmpBuf));

    char *tmpStr = (char *) (env->GetStringUTFChars(srcStringData, 0));
    if (tmpStr == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "GetStringUTFChars failed");
        return nullptr;
    } else {
        GtToolkitExt::logError(__FILE__, __LINE__, "srcStringData %s", tmpStr);
    }

    memcpy(encryptDataBuf, tmpStr, strlen(tmpStr));
    encryptDataBufLen = strlen(tmpStr);
    int ret = GtEncrypt::encryptData(4, key, 32, encryptDataBuf, sizeof(encryptDataBuf),
                                     &encryptDataBufLen);
    if (ret != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "encryptData failed,ret=%d", ret);
    }

    GtToolkitExt::logError(__FILE__, __LINE__, "encryptDataBufLen=%d", encryptDataBufLen);

    GtToolkitExt::hexToStr(encryptDataBuf, encryptDataBufLen, tmpBuf, sizeof(tmpBuf));
    return env->NewStringUTF(tmpBuf);
}

extern "C" JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_rc4DecryptData
        (JNIEnv *env, jclass obj, jstring srcStringData) {
    unsigned char key[32] = {
            0x02, 0x90, 0x52, 0xea, 0x9f, 0xff, 0xa7, 0x9d,
            0x18, 0x24, 0xe3, 0x8b, 0xdd, 0x1a, 0x14, 0xa5,
            0xed, 0xe9, 0x97, 0xb0, 0xca, 0xf2, 0xec, 0x39,
            0x81, 0x10, 0xd7, 0x9d, 0x9e, 0xba, 0x38, 0xbb
    };

    int decryptDataBufLen = 0;

    char destBuf[1024];
    memset(destBuf, 0, sizeof(destBuf));

    unsigned char decryptDataBuf[1024];
    memset(decryptDataBuf, 0, sizeof(decryptDataBuf));

    char *tmpStr = (char *) (env->GetStringUTFChars(srcStringData, 0));
    if (tmpStr == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "GetStringUTFChars failed");
        return nullptr;
    } else {
        GtToolkitExt::logError(__FILE__, __LINE__, "srcStringData %s", tmpStr);
    }

    decryptDataBufLen = strlen(tmpStr) / 2;

    int convertRet = GtToolkitExt::strToHex((unsigned char *) tmpStr, strlen(tmpStr),
                                            decryptDataBuf);
    if (convertRet != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "strToHex failed,convertRet=%d", convertRet);
    }

    int ret = GtEncrypt::decryptData(4, key, 32, decryptDataBuf, sizeof(decryptDataBuf),
                                     &decryptDataBufLen);
    if (ret != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "decryptData failed,ret=%d", ret);
    }

    GtToolkitExt::logError(__FILE__, __LINE__, "decryptDataBufLen=%d", decryptDataBufLen);

    //strcpy(destBuf,(char *)decryptDataBuf);
    memcpy(destBuf, (char *) decryptDataBuf, decryptDataBufLen);
    return env->NewStringUTF((const char *) destBuf);
}

extern "C" JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_featureCode
        (JNIEnv *env, jclass obj, jobject ticket) {
    unsigned char featureCode[16];
    char tmpBuf[256];

    memset(tmpBuf, 0, sizeof(tmpBuf));
    //C层数据转换为Java层数据
    jclass objClass = env->GetObjectClass(ticket);
    if (objClass == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    //游戏ID
    jfieldID fieldID = env->GetFieldID(objClass, "mGameID", "I");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    int gameID = env->GetIntField(ticket, fieldID);
    //游戏期号
    fieldID = env->GetFieldID(objClass, "mGameIssue", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long gameIssue = env->GetLongField(ticket, fieldID);
    //票流水号
    fieldID = env->GetFieldID(objClass, "mTicketSN", "J");
    if (fieldID == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long ticketSN = env->GetLongField(ticket, fieldID);
    //终端号
    fieldID = env->GetFieldID(objClass, "mTerminalID", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long terminalID = env->GetLongField(ticket, fieldID);
    //key
    fieldID = env->GetFieldID(objClass, "mFeatureKey", "J");
    if (fieldID == nullptr) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long featureKey = env->GetLongField(ticket, fieldID);
    env->DeleteLocalRef(objClass);
    //计算特征码
    memset(featureCode, 0, sizeof(featureCode));
    GtEncrypt::encryptFeatureCode(gameID, featureKey,
                                  gameIssue, terminalID,
                                  ticketSN, featureCode);

    GtToolkitExt::hexToStr(featureCode, 14, tmpBuf, sizeof(tmpBuf));
    return env->NewStringUTF(tmpBuf);
}

extern "C" JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_verifyCode
        (JNIEnv *env, jclass obj, jobject ticket) {
    unsigned char verifyCode[16];
    unsigned char featureCode[14];
    char tmpBuf[256];
    int outData[5][256] = {{0}};
    int outLen[5] = {0};

    memset(tmpBuf, 0, sizeof(tmpBuf));
    //C层数据转换为Java层数据
    jclass objClass = env->GetObjectClass(ticket);
    if (objClass == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    //终端ID
    jfieldID fieldID = env->GetFieldID(objClass, "mTerminalID", "J");
    if (fieldID == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long terminalID = env->GetLongField(ticket, fieldID);
    //游戏期号
    fieldID = env->GetFieldID(objClass, "mGameIssue", "J");
    if (fieldID == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long gameIssue = env->GetLongField(ticket, fieldID);
    //票流水号
    fieldID = env->GetFieldID(objClass, "mTicketSN", "J");
    if (fieldID == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long ticketSN = env->GetLongField(ticket, fieldID);
    //投注时间
    fieldID = env->GetFieldID(objClass, "mBettingTime", "J");
    if (fieldID == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    long bettingTime = env->GetLongField(ticket, fieldID);
    //投注金额
    fieldID = env->GetFieldID(objClass, "mBettingMoney", "D");
    if (fieldID == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    double bettingMoney = env->GetDoubleField(ticket, fieldID);
    //特征码
    fieldID = env->GetFieldID(objClass, "mFeatureCode", "Ljava/lang/String;");
    if (fieldID == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    jstring str = (jstring) (env->GetObjectField(ticket, fieldID));
    if (str == NULL) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    char *tmpStr = (char *) (env->GetStringUTFChars(str, 0));
    GtToolkitExt::logError(__FILE__, __LINE__, "feature %s", tmpStr);
    memset(featureCode, 0, sizeof(featureCode));
    GtToolkitExt::logError(__FILE__, __LINE__, "初始化成功");
    GtToolkitExt::strToHex((unsigned char *) tmpStr, 28, featureCode);
    //第一个投注号码
    if (GtToolkitExt::jIntArray2CIntArray2(env, ticket, (char *) "mGameBetData", outData, outLen) !=
        0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "jni数据转换错误<%d>", GtError::ERROR_INVALID_VALUE);
        return env->NewStringUTF(tmpBuf);
    }
    GtToolkitExt::logError(__FILE__, __LINE__, "初始化成功1");
    env->ReleaseStringUTFChars(str, tmpStr);
    env->DeleteLocalRef(str);
    env->DeleteLocalRef(objClass);
    //计算特征码
    GtEncrypt::encryptTicketCheckCode(terminalID, gameIssue,
                                      ticketSN, bettingTime,
                                      outData[0][0], bettingMoney,
                                      featureCode, verifyCode);
    GtToolkitExt::hexToStr(verifyCode, 16, tmpBuf, sizeof(tmpBuf));
    GtToolkitExt::logError(__FILE__, __LINE__, "verify %s", tmpBuf);
    return env->NewStringUTF(tmpBuf);
}

extern "C" JNIEXPORT jlong JNICALL Java_com_genlot_nativesdk_SystemNI_getTerminalID
        (JNIEnv *env, jclass obj) {
    stTerminal terminal;
    memset(&terminal, 0, sizeof(stTerminal));
    int result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端内存错误<%d>", result);
        return 0;
    }
    return atol(terminal.strTerminalID);
}

extern "C" JNIEXPORT jlong JNICALL Java_com_genlot_nativesdk_SystemNI_getTerminalCert
        (JNIEnv *env, jclass obj) {
    stTerminal terminal;
    memset(&terminal, 0, sizeof(stTerminal));
    int result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端内存错误<%d>", result);
        return 0;
    }
    return atol(terminal.strTerminalCert);
}

extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_setTerminalID
        (JNIEnv *env, jclass obj, jlong terminalID) {
    stTerminal terminal;
    memset(&terminal, 0, sizeof(stTerminal));
    int result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端内存错误<%d>", result);
        return result;
    }
    memset(terminal.strTerminalCert, 0, sizeof(terminal.strTerminalCert));
    memset(terminal.strTerminalID, 0, sizeof(terminal.strTerminalID));
    sprintf(terminal.strTerminalID, "%ld", (long) terminalID);
    result = GtSystem::instance()->saveTerminalConfig(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "保存终端内存错误<%d>", result);
        return result;
    }
    return 0;
}

extern "C" JNIEXPORT jstring JNICALL Java_com_genlot_nativesdk_SystemNI_getCommLine
        (JNIEnv *env, jclass obj, jint sn) {
    char tmpBuf[1024];
    stTerminal terminal;
    memset(&terminal, 0, sizeof(stTerminal));
    int result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端内存错误<%d>", result);
        return env->NewStringUTF("");
    }
    if (sn < 0) {
        return env->NewStringUTF("");
    }
    memset(tmpBuf, 0, sizeof(tmpBuf));
    if (sn == 0) {
        sprintf(tmpBuf, "%s:%d", terminal.commAttr[0].strIP1, terminal.commAttr[0].unPort1);
    } else if (sn == 1) {
        sprintf(tmpBuf, "%s:%d", terminal.commAttr[0].strIP2, terminal.commAttr[0].unPort2);
    } else if (sn == 2) {
        sprintf(tmpBuf, "%s:%d", terminal.commAttr[0].strIP3, terminal.commAttr[0].unPort3);
    } else if (sn == 3) {
        sprintf(tmpBuf, "%s:%d", terminal.commAttr[0].strIP4, terminal.commAttr[0].unPort4);
    }
    return env->NewStringUTF(tmpBuf);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_genlot_nativesdk_SystemNI_getCommIP(JNIEnv *env, jclass type, jint sn) {
    char tmpBuf[1024];
    stTerminal terminal;
    memset(&terminal, 0, sizeof(stTerminal));
    int result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端内存错误<%d>", result);
        return env->NewStringUTF("");
    }
    if (sn < 0) {
        return env->NewStringUTF("");
    }
    memset(tmpBuf, 0, sizeof(tmpBuf));
    if (sn == 0) {
        sprintf(tmpBuf, "%s", terminal.commAttr[0].strIP1);
    } else if (sn == 1) {
        sprintf(tmpBuf, "%s", terminal.commAttr[0].strIP2);
    } else if (sn == 2) {
        sprintf(tmpBuf, "%s", terminal.commAttr[0].strIP3);
    } else if (sn == 3) {
        sprintf(tmpBuf, "%s", terminal.commAttr[0].strIP4);
    }
    return env->NewStringUTF(tmpBuf);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_genlot_nativesdk_SystemNI_getCommPort(JNIEnv *env, jclass type, jint sn) {
    stTerminal terminal;
    memset(&terminal, 0, sizeof(stTerminal));
    int result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端内存错误<%d>", result);
        return 0;
    }
    if (sn < 0) {
        return 0;
    }
    if (sn == 0) {
        return terminal.commAttr[0].unPort1;
    } else if (sn == 1) {
        return terminal.commAttr[0].unPort2;
    } else if (sn == 2) {
        return terminal.commAttr[0].unPort3;
    } else if (sn == 3) {
        return terminal.commAttr[0].unPort4;
    }
    return 0;
}

extern "C" JNIEXPORT jboolean JNICALL Java_com_genlot_nativesdk_SystemNI_setCommLine
        (JNIEnv *env, jclass obj, jint sn, jstring ip, jint port) {
    char tmpBuf[1024];
    char *tmpStr = NULL;
    stTerminal terminal;

    tmpStr = (char *) (env->GetStringUTFChars(ip, 0));
    if (tmpStr == NULL) {
        return static_cast<jboolean>(false);
    }
    memset(&terminal, 0, sizeof(stTerminal));
    int result = GtMem::instance()->getMemTerminal(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "获取终端内存错误<%d>", result);
        return static_cast<jboolean>(false);
    }
    if (sn < 0) {
        return static_cast<jboolean>(false);
    }
    memset(tmpBuf, 0, sizeof(tmpBuf));
    if (sn == 0) {
        strcpy(terminal.commAttr[0].strIP1, tmpStr);
        terminal.commAttr[0].unPort1 = port;
    } else if (sn == 1) {
        strcpy(terminal.commAttr[0].strIP2, tmpStr);
        terminal.commAttr[0].unPort2 = port;
    } else if (sn == 2) {
        strcpy(terminal.commAttr[0].strIP3, tmpStr);
        terminal.commAttr[0].unPort3 = port;
    } else if (sn == 3) {
        strcpy(terminal.commAttr[0].strIP4, tmpStr);
        terminal.commAttr[0].unPort4 = port;
    }
    result = GtSystem::instance()->saveTerminalConfig(&terminal);
    if (result != 0) {
        GtToolkitExt::logError(__FILE__, __LINE__, "保存终端内存错误<%d>", result);
        return static_cast<jboolean>(false);
    }
    return static_cast<jboolean>(true);
}

extern "C" JNIEXPORT jint JNICALL Java_com_genlot_nativesdk_SystemNI_firstLoad
        (JNIEnv *env, jclass obj) {
    return GtSystem::instance()->firstLoad();
}

extern "C" JNIEXPORT jboolean JNICALL Java_com_genlot_nativesdk_SystemNI_isFirstLoad
        (JNIEnv *env, jclass obj) {
    return static_cast<jboolean>(GtSystem::instance()->isFirstLoad());
}

extern "C" JNIEXPORT jboolean JNICALL Java_com_genlot_nativesdk_SystemNI_isEnforceUpdate
        (JNIEnv *env, jclass obj) {
    stCtrlInfo ctrlInfo;
    memset(&ctrlInfo, 0, sizeof(stCtrlInfo));
    int result = GtMem::instance()->getMemCtrlInfo(&ctrlInfo);
    if (result != 0) {
        return static_cast<jboolean>(false);
    }
    return static_cast<jboolean>(((ctrlInfo.ucFileDownload & 0x80) == 0x80));
}
