/****************************************************************************
** File name    :  FLTLogger.cpp
** Description  :  logger function define
** Create date  :  2018.09.01
** Auther by    :  Liuyx
** Version info :  V1.0.01
** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd
** Update record:  
** DATE         AUTHER   DESC 
** -------------------------------------------------------------------------               
** 2018.09.01   Liuyx    first build
****************************************************************************

            ++++++++++  关于64位整数的打印说明   ++++++++++ 
 (1) windows os
     printf("int_64 = %I64d\n", int64);    -- 打印有符号64位整数
     printf("int_64 = %I64u\n", int64);    -- 打印无符号64位整数

 (2) Linux os
     printf("int_64 = %lld\n", int64);     -- 打印有符号64位整数
     printf("int_64 = %llu\n", int64);     -- 打印无符号64位整数

****************************************************************************/
//#include "StdAfx.h"
#include "HTGlobal.h"
#include "HTPublic.h"
#include "HTLogger.h"

static const char *_FILE_="HTLogger.cpp";
static char g_logger_time[15] ;        // 日志文件名称时间(YYYYMMDD)

/* mutex define */
static mutex  mutex_Debug ;  //跟踪日志
static FILE   *g_fp;
/****************************************************************
** Description : 初始化日志文件句柄锁
** param in    : None
**             : 
** param out   : None
** return code : None
****************************************************************/
void vInitLogMutex(void)
{
   	char szFile[DEF_BUFFER_256]; 

	mutex_create(mutex_Debug);

    // 创建日志文件并打开文件
	memset(szFile, 0x00, sizeof(szFile)) ;
    memset(g_logger_time, 0x00, sizeof(g_logger_time)); // 记录当前日志文件的时间(YYYYMMDD)
    vGetHostTime(g_logger_time) ;

    #ifdef _WIN32
    sprintf(szFile,"%s\\debug%.8s.log", DEF_LOG_PATH_NAME,g_logger_time) ;
    #else
    sprintf(szFile,"%s/debug%.8s.log",DEF_LOG_PATH_NAME, g_logger_time) ;
    #endif
    if(iDirOrFileExist(DEF_LOG_PATH_NAME) != 0) {
        //文件或目录不存在时, 创建文件或目录
        if(iBuildDirent(DEF_LOG_PATH_NAME) != 0) {
            printf("line:%d file:%s Create Directory:[%s] failed.\n",__LINE__,_FILE_, DEF_LOG_PATH_NAME);
            return;
        }
    } 
    g_fp = fopen((const char*)szFile, (const char*)"a+");
	if(NULL == g_fp)  {
        printf("line:%d file:%s Can't open file:[%s] failed.\n",__LINE__,_FILE_, szFile);
        return;
    }
    if(iDirOrFileExist(DEF_RUN_INFO_PATH) != 0) {
        //文件或目录不存在时, 创建文件或目录
        if((iBuildDirent(DEF_RUN_INFO_PATH)) != 0) {
            vPrtLogMsg(LOG_ERROR, errno, "Create Directory:[%s] failed,%s.", DEF_RUN_INFO_PATH,strerror(errno));
            return;
        }
    }
}
/****************************************************************
** Description : 释放日志文件句柄锁
** param in    : None
**             : 
** param out   : None
** return code : None
****************************************************************/
void vFreeLogMutex(void)
{
	mutex_close(mutex_Debug);
    if(g_fp) fclose(g_fp);
}

/**********************************************************************
** Description : 打印错误日志
** param in    : iLine           -- 行号
**             : *szFileName     -- 文件名
**             : *szErrMsg       -- 错误信息
**             : iCode           -- 报文代码 或 错误码
** param out   : None
** return code :
**             : None
**             : None
**********************************************************************/
void vPrtLogMsg(int line, const char *pszFileName, char logLevel, int iCode, /* const char *pszMsg,*/ ...)
{
	char szTime[30],szFile[DEF_BUFFER_128];  // 128
    char *p=NULL, szBuf[DEF_BUFFER_2K+1];
    va_list vl ;

    if(logLevel == __LOG_DEBUG ) {
        if(g_TConfig.isLogDebug() == 0x00 /*&& g_TConfig.isLogConsole() == 0x00  && g_TConfig.isLogMessage() == 0x00 */) return;
    }
    else if(logLevel == __LOG_WARNG) {
        if(g_TConfig.isLogWarning() == 0x00 /*&& g_TConfig.isLogConsole() == 0x00  && g_TConfig.isLogMessage() == 0x00 */) return;
    }
    else if(logLevel == __LOG_ERROR) {
        if(g_TConfig.isLogError() == 0x00 /*&& g_TConfig.isLogConsole() == 0x00  && g_TConfig.isLogMessage() == 0x00 */) return;
    }

	if(g_fp == NULL) return ;
	mutex_lock(mutex_Debug);  //lock

    //fseek(g_fp, 0l, SEEK_END) ;
    vGetHostTime(szTime) ;
    // if( ftell(g_fp) >= DEF_LOG_FILESZIE)  {  // 日志大小已经制定字节数时备份文件,并重新打开新文件
    if( memcmp(szTime, g_logger_time, 8) != 0x00 )  {  // 检查日志文件的时间是否为同一天,不是同一天时，重新产生新一天的日志文件名称
        fclose(g_fp) ;

        char szNFile[DEF_BUFFER_256];
        memset(szNFile, 0x00, sizeof(szNFile)) ;
        #ifdef _WIN32
        sprintf(szNFile, "%s\\debug%.12s.bak", DEF_LOG_PATH_NAME,szTime) ;
        sprintf(szFile,  "%s\\debug%.8s.log", DEF_LOG_PATH_NAME,szTime) ;
        #else
        sprintf(szNFile, "%s/debug%.12s.bak",  DEF_LOG_PATH_NAME,szTime) ;
        sprintf(szFile,  "%s/debug%.8s.log",DEF_LOG_PATH_NAME, szTime) ;
        #endif
        rename(szFile, szNFile) ;
     	if((g_fp = fopen(szFile,"a+")) == NULL)  {
     	    mutex_unlock(mutex_Debug);  //unlock
     	    printf("line:%d file:%s Can't open file:[%s] failed.\n",__LINE__,_FILE_, szFile);
     	    return ;
        }
        strncpy(g_logger_time, szTime, 14);     // 记录最近一次变更过的时间(YYYYMMDD)
    }
	memset(szTime,0,sizeof(szTime)) ;
    memset(szBuf, 0x00, sizeof(szBuf));

	vGetHostTimeFmt(szTime);
    
    if(logLevel == __LOG_DEBUG)  {    // 跟踪日志
        //if(g_TConfig.isLogConsole() == 0x00) 
            fprintf(g_fp,"[%s] [DEBUG]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName,  iCode);
        sprintf(szBuf,"[%s] [DEBUG]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName,  iCode);
    }
    else if(logLevel == __LOG_WARNG) { // 告警日志
        //if(g_TConfig.isLogConsole() == 0x00) 
            fprintf(g_fp,"[%s] [WARNING]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName,  iCode);
        sprintf(szBuf,"[%s] [WARNING]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName,  iCode);
    }
    else if(logLevel == __LOG_ERROR) { // 错误日志
        //if(g_TConfig.isLogConsole() == 0x00) 
            fprintf(g_fp,"[%s] [ERROR]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName,  iCode);
        sprintf(szBuf,"[%s] [ERROR]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName,  iCode);
    }
    if(g_TConfig.isLogConsole() == 0x01) {  // 屏幕输出
        printf("%s ", szBuf) ;
    }
    va_start(vl, iCode);

    while((p = va_arg(vl, char *))) {
        #ifdef _WIN32
        _vsnprintf(szBuf, sizeof(szBuf), p, vl);
        #else
        vsnprintf(szBuf, sizeof(szBuf), p, vl);
        #endif
        break;
    }
    va_end(vl);
    if(g_TConfig.isLogConsole() == 0x01) {  // 屏幕输出
        printf("%s\n", szBuf) ;
    }
    fprintf(g_fp,"%s\n",szBuf);
    fflush(g_fp);

    mutex_unlock(mutex_Debug);  //unlock
}
/*************************************************************************
** Description : 打印日志文件(16进制数据报文的打印)
** param in    : iLine          -- 打印的出处,行号
**             : *szFileName    -- 文件名
**             : *pszTitle      -- 主题提示信息
**             : *pusMsg        -- 报文数据
**             : uiMsgLen       -- 报文长度
** param out   : None
** return code : None
************************************************************************/
void vPrtLogHex(int line, const char *pszFileName,char logLevel, int sockid, /* unsigned short msg_id,  */
                const char pszMsgType, unsigned char *pusMsg,int uiMsgLen)
{
    int i, j;
    char szBuf1[80+1], szBuf2[80+1];
    char szTime[20+1], szHex[3+1];
    char szFile[DEF_BUFFER_256];
    char szTitle[1024]={0};

    if(g_TConfig.isLogPack() == 0x00) return ;

    if(g_fp == NULL) return ;
    mutex_lock(mutex_Debug);  //lock
    
	//fseek(g_fp, 0l, SEEK_END) ;
    vGetHostTime(szTime) ;
    if( memcmp(szTime, g_logger_time, 8) != 0x00)  {  // 检查日志文件的时间是否为同一天,不是同一天时，重新产生新一天的日志文件名称
    // if(ftell(g_fp) >= DEF_LOG_FILESZIE) {
        fclose(g_fp) ;
        
        char szNFile[DEF_BUFFER_256];
        memset(szNFile, 0x00, sizeof(szNFile)) ;
        #ifdef _WIN32
        sprintf(szNFile, "%s\\debug%.12s.bak", DEF_LOG_PATH_NAME,szTime) ;
        sprintf(szFile,  "%s\\debug%.8s.log",DEF_LOG_PATH_NAME, szTime) ;
        #else
        sprintf(szNFile, "%s/debug%.12s.bak",  DEF_LOG_PATH_NAME,szTime) ;
        sprintf(szFile,  "%s/debug%.8s.log",DEF_LOG_PATH_NAME, szTime) ;
        #endif
        rename(szFile, szNFile) ;
     	if((g_fp = fopen(szFile,"a+")) == NULL)  {
     	    mutex_unlock(mutex_Debug);  //unlock
            printf("line:%d file:%s Can't open file:[%s] failed.\n",__LINE__, _FILE_, szFile);
     	    return ;
        }
        strncpy(g_logger_time, szTime,14);  // 记录最近一次变更过的时间(YYYYMMDD) 
    }
    vGetHostTimeFmt( szTime ) ; /* 获取系统时间 */
    if(pszMsgType == PRT_PACK_SEND) {
        fprintf(g_fp, "[%s] [DEBUG]-%ld Line:%d %s --> [SendData] sockid:%d  length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen);
        sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s --> [SendData] sockid:%d  length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen);
    }
    else if(pszMsgType == PRT_PACK_RECV) {
        fprintf(g_fp, "[%s] [DEBUG]-%ld Line:%d %s --> [RecvData] sockid:%d  length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen);
        sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s --> [RecvData] sockid:%d  length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen);
    }
    else  {
        fprintf(g_fp, "[%s] [DEBUG]-%ld Line:%d %s --> [PrntData] sockid:%d  length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen);
        sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s --> [PrntData] sockid:%d  length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen);
    }
    if(g_TConfig.isLogConsole() == 0x01) {  // 屏幕输出
        printf("%s", szTitle);
    }
    sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s", szTime,GETTID(),line,pszFileName) ;

    for(i=0; i<uiMsgLen; i+=16, pusMsg+=16)
    {
        memset(szBuf1, 0, sizeof(szBuf1));
        sprintf(szBuf1, "%04XH  ",i);
        memset(szBuf2, 0, sizeof(szBuf2));
        for(j=0; j<16; j++)
        {
            if( (uiMsgLen-i) < 16 && j >= (uiMsgLen%16) )
                break;
            sprintf(szHex, "%02X ", pusMsg[j]&0xFF);
            strcat(szBuf1, szHex);
            if(j==7)
                strcat(szBuf1, "  ");
            if(pusMsg[j]>0x20 && pusMsg[j]<0x0ff)
                szBuf2[j] = pusMsg[j];
            else
                szBuf2[j] = '_';
        }
        for(; j<16; j++)
        {
           if(j==7)
                strcat(szBuf1, "  ");
           strcat(szBuf1, "   ");
        }
        fprintf(g_fp, "%s --> %s  %s\n", szTitle, szBuf1, szBuf2);
        if(g_TConfig.isLogConsole() == 0x01) {  // 屏幕输出
            printf("%s --> %s  %s\n", szTitle, szBuf1, szBuf2);
        }
    }
    fflush(g_fp);  // 写入文件
    mutex_unlock(mutex_Debug);  //unlock
}

