#ifndef __LOG_H__
#define __LOG_H__

#ifdef __cplusplus
#ifndef BEGIN_DECLS
#define BEGIN_DECLS extern "C" {
#endif
#ifndef END_DECLS
#define END_DECLS }
#endif
#else
#ifndef BEGIN_DECLS
#define BEGIN_DECLS
#endif
#ifndef END_DECLS
#define END_DECLS
#endif
#endif

BEGIN_DECLS

#if defined(_WIN32) && defined(UNICODE)
#include <wchar.h>
#endif

#include <stddef.h>

#include <limits.h>
#ifdef _WIN32
//#include <windows.h>
#else
#include <execinfo.h>
#endif
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
/*
#include <stddef.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <linux/limits.h>
#include <stdlib.h>
#include <ctype.h>
*/


#include "Common.h"
#include "SecureCodingUtil.h"
#include "Config.h"


#define LOG_MAX_BUFFER_SIZE		                     8192
#define LOG_TIME_STRING_SIZE                            14
#define LOG_COMM_TIME_STRING_SIZE                       16

#define LOG_ERR_SUCCESS                                 0
#define LOG_ERR_CONFIG                                  -1
#define LOG_ERR_MEM                                     -2

#define LOG_COMM_LOG_SUBFOLDER                          "comm"

#define LOG_LOG_FILE_ROOT_KEY                           "LOG_FILE_PATH"

#define LOG_SYS_LOG_FILENAME_KEY                        "SYS_LOG_FILENAME"
#define LOG_SYS_LOG_LOGLEVEL_KEY                        "SYS_LOG_LEVEL"
#define LOG_SYS_LOG_FILENAME_USE_PROCNAME_KEY           "SYS_LOG_FILENAME_USE_PROCNAME"
#define LOG_ERROR_LOG_FILENAME_KEY                      "ERROR_LOG_FILENAME"
#define LOG_ERROR_LOG_LEVEL_KEY                         "ERROR_LOG_LEVEL"
#define LOG_ERROR_LOG_FILENAME_USE_PROCNAME_KEY         "ERROR_LOG_FILENAME_USE_PROCNAME"
#define LOG_STANDARD_LOG_FILENAME_KEY                   "STANDARD_LOG_FILENAME"
#define LOG_STANDARD_LOG_LEVEL_KEY                      "STANDARD_LOG_LEVEL"
#define LOG_STANDARD_LOG_FILENAME_USE_PROCNAME_KEY      "STANDARD_LOG_FILENAME_USE_PROCNAME"
#define LOG_COMM_LOG_FILENAME_KEY                       "COM_LOG_FILENAME"
#define LOG_COMM_LOG_LEVEL_KEY                          "COM_LOG_LEVEL"
#define LOG_COMM_LOG_FILENAME_USE_PROCNAME_KEY          "COM_LOG_FILENAME_USE_PROCNAME"
#define LOG_MQ_LOG_FILENAME_KEY                         "MQ_LOG_FILENAME"
#define LOG_MQ_LOG_LEVEL_KEY                            "MQ_LOG_LEVEL"
#define LOG_MQ_LOG_FILENAME_USE_PROCNAME_KEY            "MQ_LOG_FILENAME_USE_PROCNAME"

#define LOG_MAX_TRACE_STACK_FRAMES                      64


enum LogLevel
{
    LogLevel_Off            = 0x00,         // 로그 사용하지 않음
    LogLevel_Trace          = 0x01,         // Trace 레벨 정보 저장   - 프로그램 오류 발생시 추적을 위한 trace 정보 저장 레벨
    LogLevel_Debug          = 0x02,         // Debug 레벨 정보 저장   - 프로그램 오류 체크를 위해서만 사용하고 실제 운영시 사용하지 않는 레벨
    LogLevel_Info           = 0x04,         // Info 레벨 정보 저장    - 일반적인 사항 외에 추가적인 정보를 저장하기 위한 로그 레벨
    LogLevel_Warning        = 0x08,         // Warning 레벨 정보 저장 - 경고성 메시지 레벨
    LogLevel_Error          = 0x10,         // Error 메시지 정보 저장      - 오류 메시지 레벨
    LogLevel_Fatal          = 0x20          // 치명적인 오류 정보 저장        - 치명적인 오류 발생 시 필요한 정보를 저장하기 위한 레벨
};

//countable_enum(LogType, StandardOut, ErrorOut, SystemOut, CommOut);

enum LogType
{
    LogType_StandardOut     = 0,            // 표준 출력으로 일반적인 사항(전문 처리 내용 등)을 저장하는 로그 파일
    LogType_ErrorOut,                       // 오류 내용을 저장하는 로그 파일
    LogType_SystemOut,                      // 시스템 정보를 저장하는 파일로 주로 프로그램 시작, 종료 등을 저장
    LogType_CommOut,                        // 통신 내용을 저장하는 통신 로그
    LogType_MQOut,                          // 메시지 큐 처리 로그
    LogType_Count                           // enum 요소 카운트
};

struct LOGFILEINFO
{
    char            szFileName[PATH_MAX + 1];
    enum LogType    eLogType;
    int             nLogLevelFlags;
    int            bUseProcessnameInFilename;
};

struct LOGLEVELINFO
{
    int nBitFlag;
    char szLogLevel[MAX_STRING_SIZE + 1];
};

int InitLogConfig();
int ParsingLogTypeTag(const char *szTags, const int nInputTagLength);
void WriteTraceLog(enum LogType eLogType, enum LogLevel eLogLevel, const char *szFilename, long nLinenumber, const char *szFunctionname, const char *szFormat, ...);
void WriteLog(enum LogType eLogType, enum LogLevel eLogLevel, const char *szFormat, ...);
void WriteRawCommLog(enum LogType eLogType, enum LogLevel eLogLevel, int nSocket, char cSendRecv, const char *szFormat, ...);
void WriteCommLog(enum LogType eLogType, enum LogLevel eLogLevel, int nSocket, int nChannelNo, char cSendRecv, const char *szFormat, ...);
void WriteQueueLog(enum LogType eLogType, enum LogLevel eLogLevel, int nSocket, char cType, const char *szExchanger, const char *szTopic, const char *szUUID, int nLength, const char *szFormat, ...);


END_DECLS

#endif
