#ifndef __DEBUG_UTIL_H__
#define __DEBUG_UTIL_H__

#include <syslog.h>
#include <time.h>
#include <sys/time.h>
#include <sys/syscall.h>

#ifdef __cplusplus
extern "C" {
#endif

#define COLOR_DISPLAY 1

#define gettid() syscall(__NR_gettid)

#define DBG_LEVEL_EMERG             LOG_EMERG
#define DBG_LEVEL_ALERT             LOG_ALERT
#define DBG_LEVEL_CRIT              LOG_CRIT
#define DBG_LEVEL_ERR               LOG_ERR
#define DBG_LEVEL_WARNING           LOG_WARNING
#define DBG_LEVEL_NOTICE            LOG_NOTICE
#define DBG_LEVEL_INFO              LOG_INFO
#define DBG_LEVEL_DEBUG             LOG_DEBUG

#ifdef COLOR_DISPLAY

//"\033[0;32;31m<EMERG>" //red
//"\033[0;32;31m<ALERT>" //red
//"\033[0;32;31m<CRIT>" //red
//"\033[0;32;31m<ERR>" //red
//"\033[1;31m<WARN>" //light red
//"\033[1;37m<NOTICE>" //white
//"\033[1;33m<INFO>" //yellow
 //"\033[m<NONE>"//none
 //"\033[0;32;32m<DEBUG>"  green

#define LOG_STRING(level)          ((level == LOG_EMERG) ? "\033[0;32;31m<EMERG>" :        \
                                    (level == LOG_ALERT) ? "\033[0;32;31m<ALERT>" :                        \
                                    (level == LOG_CRIT) ? "\033[0;32;31m<CRIT>" :                          \
                                    (level == LOG_ERR) ? "\033[0;32;31m<ERR>" :                            \
                                    (level == LOG_WARNING) ? "\033[1;31m<WARN>" :        \
                                    (level == LOG_NOTICE) ? "\033[1;37m<NOTICE>" :         \
                                    (level == LOG_INFO) ? "\033[1;33m<INFO>" :                \
                                    (level == LOG_DEBUG) ? "\033[0;32;32m<DEBUG>" : "\033[m<NONE>")
#else
#define LOG_STRING(level)          ((level == LOG_EMERG) ? "EMERG" :                        \
                                    (level == LOG_ALERT) ? "ALERT" :                        \
                                    (level == LOG_CRIT) ? "CRIT" :                          \
                                    (level == LOG_ERR) ? "ERR" :                            \
                                    (level == LOG_WARNING) ? "WARNING" :                    \
                                    (level == LOG_NOTICE) ? "NOTICE" :                      \
                                    (level == LOG_INFO) ? "INFO" :                          \
                                    (level == LOG_DEBUG) ? "DEBUG" : "NONE")
#endif

#define LOG(level, fmt, args...)                                                         \
    do                                                                                      \
    {                                                                                       \
        if (level <= DBG_LEVEL_DEBUG)                                                       \
        {                                                                                   \
            time_t tp;                                                                      \
            struct tm * timeinfo;                                                           \
            struct timeval tv;                                                              \
            static char time_buf[32];                                                       \
            static char sprintf_buf[2048] = {0};                                            \
            time(&tp);                                                                      \
            timeinfo = localtime(&tp);                                                      \
            strftime(time_buf, 32, "%Y-%m-%d %H:%M:%S", timeinfo);                          \
            gettimeofday(&tv, NULL);                                                        \
            memset(sprintf_buf, 0, sizeof(sprintf_buf));                                    \
            snprintf(sprintf_buf, sizeof(sprintf_buf), "%s %ld %s.%ld %s:%ld# "fmt"\033[m",         \
                LOG_STRING(level),                                                          \
                (long int)gettid(),                                                         \
                time_buf,                                                                   \
                (long int)tv.tv_usec,                                                       \
                __FILE__,                                                                   \
                (long int)__LINE__,                                                         \
                ##args);                                                                    \
            syslog(level, "%s", sprintf_buf);                                               \
            printf("%s", sprintf_buf);                                                      \
        }                                                                                   \
    } while(0)

#define UTIL_LOG_DBG(fmt, args...)        LOG(DBG_LEVEL_DEBUG, fmt, ##args)
#define UTIL_LOG_INFO(fmt, args...)       LOG(DBG_LEVEL_INFO, fmt, ##args)
#define UTIL_LOG_WARNING(fmt, args...)    LOG(DBG_LEVEL_WARNING, fmt, ##args)
#define UTIL_LOG_ERR(fmt, args...)        LOG(DBG_LEVEL_ERR, fmt, ##args)

#define DEBUG_LOG_OPENLOG(ident)               openlog(ident, LOG_CONS | LOG_PID, LOG_USER)    //call:DEBUG_LOG_OPENLOG("host");
#define DEBUG_LOG_CLOSELOG()                   closelog()

#ifdef __cplusplus
}
#endif

#endif /* __DEBUG_UTIL_H__ */
