/****************************************************************************
** File name    :  HTIEC61850FileParser.cpp
** Description  :  define iec 61850 dat file parser api
** Create date  :  2019.09.01
** Auther by    :  Liuyx
** Version info :  V1.0.01
** Copyrigth By:  xi'an huatek, Inc Co., Ltd
** Update record:
** DATE         AUTHER   DESC
** -------------------------------------------------------------------------
** 2019.09.01   Liuyx    first build
****************************************************************************/
#include "HTGlobal.h"
static const char *_FILE_ = "HTIEC61850FileParser.cpp";


/* 扫码谱图文件*.dat文件
pPath   :   path, eg: /usr/local/img/*.dat
: "D:\\Photo and Video\\destop1\\*.dat";
*/
int iSacnComtradeFileList(const char *pPath, std::vector<cv::String> & image_files)
{
    cv::String pattern_jpg = (char*)pPath;
    //std::vector<cv::String> image_files;
    try{
        cv::glob(pattern_jpg, image_files);
        if (image_files.size() == 0) {
            return 0;
        }
        return (int)image_files.size();
    }
    catch (cv::Exception &e)
    {
        vPrtLogMsg(LOG_WARNG, RET_FAIL, "scanf comtrad exception,msg:%s\n", e.err.c_str());
    }
    return 0;
}

/*****************************************************************************
* thread_sacnfile_proc - 扫描谱图文件
******************************************************************************/
static void getIECFileList()
{
    char szSql[DEF_BUFFER_1K] = { 0 };
    CDBMySQL *pdbHandle = CDBMySQL::Instance();
    if (!pdbHandle) return;

    sprintf(szSql, "select id,pd_file from iec_pd_file_header where state='2' ");
    MYSQL_RES *res = pdbHandle->SelectRecord(szSql);
    if (!res)  return;

    MYSQL_ROW row = NULL;
    while (row = pdbHandle->GetRecord(res))
    {
        ST_FILE61850_LIST stFileList;
        memset(&stFileList, 0x00, sizeof(ST_FILE61850_LIST));

        if (row[0] && strlen(row[0]) > 0) {
            strncpy((char*)stFileList.id, (const char*)row[0], sizeof(stFileList.id));
        }

        if (row[1] && strlen(row[1]) > 0) {
            strncpy((char*)stFileList.szFileName, (const char*)row[1], sizeof(stFileList.szFileName));
        }
        mutex_lock(g_list_file_mutex);
        g_list_file.push_front(stFileList);
        mutex_unlock(g_list_file_mutex);
    }
    pdbHandle->FreeRecord(res);
    return;
}

// 数据入库/更新数据
static void setdbParserData(const char *pszSql)
{
    char szSql[DEF_BUFFER_1K] = { 0 };
    CDBMySQL *pdbHandle = CDBMySQL::Instance();
    if (!pdbHandle) return;
    
    pdbHandle->InsertRecord(szSql);
    
    return;
}
/*****************************************************************************
* thread_sacnfile_proc - 扫描谱图文件
******************************************************************************/
void *thread_sacnfile_proc(void *arg)
{
    vPrtLogMsg(LOG_DEBUG, 0, "thread_sacnfile_proc = %d startup...", GETTID());
    int  filecount = 0;
    char szDestfile[DEF_BUFFER_1K], szTmp[MAX_PATH] = { 0 };
    while (g_Running)
    {
        // getIECFileList();
#ifdef _WIN32
        sprintf(szDestfile, "%s\\*.dat", g_TConfig.getIecComtradeHomePath());
#else
        sprintf(szDestfile, "%s/*.dat", g_TConfig.getIecComtradeHomePath());
#endif
        std::vector<cv::String> vecFileList;
        filecount = iSacnComtradeFileList(szDestfile, vecFileList); // 扫描文件列表
        // 逐个文件分析
        for (int n = 0; n < filecount; n++)
        {
            // 目录转为Linux格式
        #ifndef _WIN32
            Window2UnixPath((char*)vecFileList[n].c_str());
        #endif
            strncpy(szTmp, (const char*)vecFileList[n].c_str(), vecFileList[n].length());
            ST_FILE61850_LIST stFileList;
            
            memset(szDestfile, 0x00, sizeof(szDestfile));
            bSplitFilenameByPath((char*)vecFileList[n].c_str(), szDestfile, szTmp);            

            memset(&stFileList, 0x00, sizeof(ST_FILE61850_LIST));
            getuuid((char*)stFileList.id, sizeof(stFileList.id));
            strcpy((char*)stFileList.szFileName, szTmp);
            
            mutex_lock(g_list_file_mutex);
            g_list_file.push_front(stFileList);
            vPrtLogMsg(LOG_DEBUG, 0, "thread_sacnfile_proc file_count= %d", g_list_file.size());
            mutex_unlock(g_list_file_mutex);
        }
        _SLEEP(1000 * 60);
        //_SLEEP(10);
    }
    return NULL;
}


/***************************************************************************
** function name :  thread_file_parser_proc
** deacription   :  db opration thread and mysql insert...
** parameter     :  none
** return code   :  NULL
***************************************************************************/
void *thread_file_parser_proc(void *arg)
{
    vPrtLogMsg(LOG_DEBUG, 0, "thread_file_parser_proc = %d startup...", GETTID());
    ST_FILE61850_LIST stFileList;
    char szFile[DEF_BUFFER_256],szDestPath[DEF_BUFFER_256];
    while (g_Running)
    {
        pthread_testcancels();
        memset(&stFileList, 0x00, sizeof(ST_FILE61850_LIST));
        mutex_lock(g_list_file_mutex);
        if (g_list_file.empty() || g_list_file.size() <= 0) {
            mutex_unlock(g_list_file_mutex);
            _SLEEP(MAX_SLEEP_EMPTY * 10);
            continue;
        }
        memcpy(&stFileList, &(g_list_file.back()), sizeof(ST_FILE61850_LIST));  // 由尾取出   
        g_list_file.pop_back(); // 由尾删除
        vPrtLogMsg(LOG_DEBUG, 0, "thread_file_parser_proc file_count= %d", g_list_file.size());
        mutex_unlock(g_list_file_mutex);

        csgIEC61850PdFileParser(stFileList);

        memset(szFile, 0x00, sizeof(szFile));
        memset(szDestPath, 0x00, sizeof(szDestPath));
        // 将分析过的文件移到指定目录下
#ifdef _WIN32
        sprintf(szFile, "%s\\%s", g_TConfig.getIecComtradeHomePath(), stFileList.szFileName);
        sprintf(szDestPath, "%s\\", g_TConfig.getIecComtradeBakPath());
#else
        sprintf(szFile, "%s/%s", g_TConfig.getIecComtradeHomePath(), stFileList.szFileName);
        sprintf(szDestPath, "%s/", g_TConfig.getIecComtradeBakPath());
#endif
        bMoveFile(szFile, szDestPath);  // 备份dat文件到指定的目录下。
    }
    return NULL;
}

/***************************************************************************
** function name :  thread_db_insert_proc
** deacription   :  db opration thread and mysql insert...
** parameter     :  none
** return code   :  NULL
***************************************************************************/
void *thread_db_insert_proc(void *arg)
{
    vPrtLogMsg(LOG_DEBUG, 0, "thread_db_insert_proc = %d startup...", GETTID());
    MYSQL *pMySql = NULL;
    int count = 0; 
    while (g_Running)
    {
        pthread_testcancels();
        mutex_lock(g_list_dbsql_mutex);
        count = g_list_dbsql.size();
        if (g_list_dbsql.empty() || g_list_dbsql.size() <= 0) {
            mutex_unlock(g_list_dbsql_mutex);
            _SLEEP(MAX_SLEEP_EMPTY * 10);
            continue;
        }

        // 准备数据库操作
        CDBMySQL *pdbHandle = CDBMySQL::Instance();
        if (!pdbHandle) {
            mutex_unlock(g_list_dbsql_mutex);
            _SLEEP(MAX_SLEEP_EMPTY * 5);
            continue;
        }
        pMySql = pdbHandle->GetIdleMySql();
        if (pMySql == NULL) {
            mutex_unlock(g_list_dbsql_mutex);
            vPrtLogMsg(LOG_WARNG, RET_FAIL, "GetIdleMySql handle failed.");
            _SLEEP(MAX_SLEEP_EMPTY);
            continue;
        }
        pdbHandle->dbAutoCommit(pMySql, false);
        for (int n = 0; n < (count > 100 ? 100 : count); n++)
        {
            ST_DB_INSERT_LIST stSqlList;
            memset(&stSqlList, 0x00, sizeof(ST_DB_INSERT_LIST));
            memcpy(&stSqlList, &(g_list_dbsql.back()), sizeof(ST_DB_INSERT_LIST));  // 由尾取出
            g_list_dbsql.pop_back(); // 由尾删除
            
            if ((stSqlList.cOpt & 0xff) == DB_OPT_INSERT)
                pdbHandle->AddInsertRecord(pMySql, stSqlList.pBuf);
            else if ((stSqlList.cOpt & 0xff) == DB_OPT_UPDATE)
                pdbHandle->UpdateRecord(stSqlList.pBuf);
            if (stSqlList.pBuf) {
                free(stSqlList.pBuf);
                stSqlList.pBuf = NULL;
            }
        }
        pdbHandle->dbCommit(pMySql);
        pdbHandle->dbAutoCommit(pMySql, true);
        pdbHandle->SetIdleMysql(pMySql);
        mutex_unlock(g_list_dbsql_mutex);
        _SLEEP(MAX_SLEEP_EMPTY * 10);
    }
    return NULL;
}
