//
// Created by Ht on 2019/8/13.
//


/**
 *
 *      Logger相关的处理
 *      需要增加：
 *      1、写到日志文件，支持多日志文件和多日志域分区记录，支持关键字过滤显示
 *      2、广播到网络中，支持远程读取设备日志， 必须输出key，才能读取日志
 *      3、支持通过QConfigUtil，读取端口和广播关键字和Key的配置
 *
 */
#ifndef JSONPROTOCOL_QLOGGER_H
#define JSONPROTOCOL_QLOGGER_H

#include <string>

#include <jebase/config.h>
#include <cross/sysdef.h>
#include <functional>

#ifdef ANDROID
#include <sys/time.h>
#endif

#ifdef __cplusplus
extern "C"
#endif
JE_API const char* __Loger_FileName(const char* org_file_name);

namespace qlibc {

    static const char* sval_log_domain_main = "main";

    static const unsigned short ival_log_listen_port = 3010;

    static const char* sval_log_default_listen_key = "qlogger";

    static const char* vkey_log_listen_port = "qlog_port";

    static const char* vkey_log_listen_key = "qlog_key";

    static const char* sval_default_action = "je";

    using QLogCallback = std::function<void(const char* action, int type, const char* logStr)>;
    using QAfterLogged = std::function<void(void)>;

//各种log颜色
#define qlog_none         "\033[0m"
#define qlog_black        "\033[0;30m"
#define qlog_dark_gray    "\033[1;30m"
#define qlog_blue         "\033[0;34m"
#define qlog_light_blue   "\033[1;34m"
#define qlog_green        "\033[0;32m"
#define qlog_light_green  "\033[1;32m"
#define qlog_cyan         "\033[0;36m"
#define qlog_light_cyan   "\033[1;36m"
#define qlog_red          "\033[0;31m"
#define qlog_light_red    "\033[1;31m"
#define qlog_purple       "\033[0;35m"
#define qlog_light_purple "\033[1;35m"
#define qlog_brown        "\033[0;33m"
#define qlog_yellow       "\033[1;33m"
#define qlog_light_gray   "\033[0;37m"
#define qlog_white        "\033[1;37m"

#define qlog_LOG             qlog_none
#define qlog_WARN            qlog_brown
#define qlog_INFO            qlog_purple
#define qlog_ERR             qlog_red
#define qlog_HighLight       qlog_light_cyan
#define qlog_Mark            qlog_light_blue
#define qlog_Comment         qlog_yellow
#define qlog_EMark           qlog_light_green

    enum QLoggerType {
        QLT_Log = 0,
        QLT_Warn,
        QLT_Info,
        QLT_Err,
        QLT_Mark,
        QLT_HighLight,
        QLT_Comment,
        QLT_EMark,
    };

    class JE_API QLogger {
    public:
        static bool promptPrinted();

        static void markPromptPrinted();

        static void unmarkPromptPrinted();

        static void afterUserLogged();

        static void simpleLogDo(const char* action, const char* color, const char *format, ...);

        static void simpleLogDoRaw(const char* color, const char *format, ...);

        static void UserLogDo(const char* action, QLoggerType type, const char *format, ...);

        static void UserLogDoRaw(QLoggerType type, const char *format, ...);

        static void systemTLog(QLoggerType type, const char *format, ...);

        static void systemTLogRaw(QLoggerType type, const char *format, ...);

        static void appendLogCallback(const std::string& key, const QAfterLogged& cb);

        static void removeLogCallback(const std::string& key);

        static void release();

        static void initLoggerPlugs();

        static std::string getTimePrefix(bool showThreadLabel = true);

        static void switchTimePrefix();

        static void setGrep(const char *fmt, ...);

        static std::string getSelfThreadLabel();

        static void setLogCallback(const std::string& key, const QLogCallback& callback);

        static void clearLogCallback(const std::string& key);

        static void highlightValueSystemSimpleLog(const char* action,QLoggerType type, const char* cfmt, const std::string& val, bool tryPlug);

        static void highlightValueUserLog(const char* action, QLoggerType type, const char* cfmt, const std::string& val, bool tryPlug);

        static bool isLoggerCallbackSet(const std::string &loggerKey);

        static void clearColorSign(std::string& log);
    };

#define MarkLogged qlibc::QLogger::afterUserLogged();
#ifdef DEBUG
#define ULog(type, pChr, ...) \
    qlibc::QLogger::UserLogDo(qlibc::sval_default_action, (type), (std::string("[%s:%16s:%-4d(%16s)]")+pChr).c_str(),qlibc::QLogger::getTimePrefix().c_str(),__Loger_FileName(__FILE__),__LINE__,__FUNCTION__, ##__VA_ARGS__)
#define ULogC(color, pChr, ...) \
    qlibc::QLogger::simpleLogDo(qlibc::sval_default_action, (color), (std::string("[%s:%16s:%-4d(%16s)]")+pChr).c_str(),qlibc::QLogger::getTimePrefix().c_str(),__Loger_FileName(__FILE__),__LINE__,__FUNCTION__,##__VA_ARGS__)
#define ULogR(type, pChr, ...) \
    qlibc::QLogger::UserLogDoRaw(type, (std::string("[%s:%16s:%-4d(%16s)]")+pChr).c_str(),qlibc::QLogger::getTimePrefix().c_str(),__Loger_FileName(__FILE__),__LINE__,__FUNCTION__,##__VA_ARGS__)
#define UALog(action, type, pChr, ...) \
    qlibc::QLogger::UserLogDo((action), type, (std::string("[%s:%16s:%-4d(%16s)]")+pChr).c_str(),qlibc::QLogger::getTimePrefix().c_str(),__Loger_FileName(__FILE__),__LINE__,__FUNCTION__, ##__VA_ARGS__)
#else
#define ULog(type, pChr, ...)       qlibc::QLogger::UserLogDo(qlibc::sval_default_action, (type), (std::string("%s ")+pChr).c_str(), qlibc::QLogger::getTimePrefix().c_str(),##__VA_ARGS__)
#define ULogC(color, pChr, ...)     qlibc::QLogger::simpleLogDo(qlibc::sval_default_action, (color), (std::string("%s ")+pChr).c_str(), qlibc::QLogger::getTimePrefix().c_str(), ##__VA_ARGS__)
#define ULogR(type, pChr, ...) \
    qlibc::QLogger::UserLogDoRaw(type, (std::string("%s ")+pChr).c_str(), qlibc::QLogger::getTimePrefix().c_str(),##__VA_ARGS__)
#define UALog(action, type, pChr, ...)       qlibc::QLogger::UserLogDo((action), (type), (std::string("%s ")+pChr).c_str(), qlibc::QLogger::getTimePrefix().c_str(),##__VA_ARGS__)
#endif

#define QLog(pChr,...)  ULog(qlibc::QLT_Log, pChr, ##__VA_ARGS__)
#define QErr(pChr,...)  ULog(qlibc::QLT_Err, pChr, ##__VA_ARGS__)
#define QWarn(pChr,...) ULog(qlibc::QLT_Warn, pChr, ##__VA_ARGS__)
#define QInfo(pChr,...) ULog(qlibc::QLT_Info, pChr, ##__VA_ARGS__)
#define QMark(pChr,...) ULog(qlibc::QLT_Mark, pChr, ##__VA_ARGS__)
#define QHLog(pChr,...) ULog(qlibc::QLT_HighLight, pChr, ##__VA_ARGS__)
#define QCmt(pChr,...)  ULog(qlibc::QLT_Comment, pChr, ##__VA_ARGS__)
#define QEMark(pChr,...) ULog(qlibc::QLT_EMark, pChr, ##__VA_ARGS__)

#define QALog(action,pChr,...)  UALog(action,qlibc::QLT_Log, pChr, ##__VA_ARGS__)
#define QAErr(action,pChr,...)  UALog(action,qlibc::QLT_Err, pChr, ##__VA_ARGS__)
#define QAWarn(action,pChr,...) UALog(action,qlibc::QLT_Warn, pChr, ##__VA_ARGS__)
#define QAInfo(action,pChr,...) UALog(action,qlibc::QLT_Info, pChr, ##__VA_ARGS__)
#define QAMark(action,pChr,...) UALog(action,qlibc::QLT_Mark, pChr, ##__VA_ARGS__)
#define QAHLog(action,pChr,...) UALog(action,qlibc::QLT_HighLight, pChr, ##__VA_ARGS__)
#define QACmt(action,pChr,...)  UALog(action,qlibc::QLT_Comment, pChr, ##__VA_ARGS__)
#define QAEMark(action,pChr,...) UALog(action,qlibc::QLT_EMark, pChr, ##__VA_ARGS__)

#define QLogR(pChr,...)  ULogR(qlibc::QLT_Log, pChr, ##__VA_ARGS__)
#define QErrR(pChr,...)  ULogR(qlibc::QLT_Err, pChr, ##__VA_ARGS__)
#define QWarnR(pChr,...) ULogR(qlibc::QLT_Warn, pChr, ##__VA_ARGS__)
#define QInfoR(pChr,...) ULogR(qlibc::QLT_Info, pChr, ##__VA_ARGS__)
#define QMarkR(pChr,...) ULogR(qlibc::QLT_Mark, pChr, ##__VA_ARGS__)
#define QHLogR(pChr,...) ULogR(qlibc::QLT_HighLight, pChr, ##__VA_ARGS__)
#define QCmtR(pChr,...)  ULogR(qlibc::QLT_Comment, pChr, ##__VA_ARGS__)
#define QEMarkR(pChr,...) ULogR(qlibc::QLT_EMark, pChr, ##__VA_ARGS__)

#define SLog(pChr,...)  qlibc::QLogger::systemTLog(qlibc::QLT_Log, pChr, ##__VA_ARGS__)
#define FLog(pChr,...)  qlibc::QLogger::simpleLogDo(qlibc::sval_default_action, qlog_none, pChr, ##__VA_ARGS__)

#define SLogR(pChr,...)  qlibc::QLogger::systemTLogRaw(qlibc::QLT_Log, pChr, ##__VA_ARGS__)
#define FLogR(pChr,...)  qlibc::QLogger::simpleLogDoRaw(qlog_none, pChr, ##__VA_ARGS__)

#define HVFLog(pChar, v) qlibc::QLogger::highlightValueSystemSimpleLog(qlibc::sval_default_action, qlibc::QLT_HighLight, pChar,v, true)
#define MKFLog(pChar, v) qlibc::QLogger::highlightValueSystemSimpleLog(qlibc::sval_default_action, qlibc::QLT_EMark, pChar,v, true)
#define ERFLog(pChar, v) qlibc::QLogger::highlightValueSystemSimpleLog(qlibc::sval_default_action, qlibc::QLT_Err, pChar,v, true)
#define HVFLogR(pChar, v) qlibc::QLogger::highlightValueSystemSimpleLog(qlibc::sval_default_action, qlibc::QLT_HighLight, pChar,v, false)
#define MKFLogR(pChar, v) qlibc::QLogger::highlightValueSystemSimpleLog(qlibc::sval_default_action, qlibc::QLT_EMark, pChar,v, false)
#define ERFLogR(pChar, v) qlibc::QLogger::highlightValueSystemSimpleLog(qlibc::sval_default_action, qlibc::QLT_Err, pChar,v, false)
#define HVULogR(pChar, v) qlibc::QLogger::highlightValueUserLog(qlibc::sval_default_action, qlibc::QLT_HighLight, (qlibc::QLogger::getTimePrefix()+" "+pChar).c_str(),v, true)
#define MKULogR(pChar, v) qlibc::QLogger::highlightValueUserLog(qlibc::sval_default_action, qlibc::QLT_EMark, (qlibc::QLogger::getTimePrefix()+" "+pChar).c_str(),v, true)
#define ERULogR(pChar, v) qlibc::QLogger::highlightValueUserLog(qlibc::sval_default_action, qlibc::QLT_Err, (qlibc::QLogger::getTimePrefix()+" "+pChar).c_str(), v, true)

#define LOG_GREP(key, ...) \
    qlibc::QLogger::setGrep(key, ##__VA_ARGS__, nullptr)

#define QLogHexStr(fmt, buff, len) \
    QLog(fmt, NumberUtils::bytesToHexStr(buff, len).c_str());
#define QWarnHexStr(fmt, buff, len) \
    QWarn(fmt, NumberUtils::bytesToHexStr(buff, len).c_str());

#ifdef DEBUG
#define QDLog(pchar, ...) QLog(pchar, ##__VA_ARGS__)
#define QDErr(pchar, ...) QErr(pchar, ##__VA_ARGS__)
#define QDWarn(pChr,...) QWarn(pChr,##__VA_ARGS__)
#define QDInfo(pChr,...) QInfo(pChr,##__VA_ARGS__)
#define QDMark(pChr,...) QMark(pChr,##__VA_ARGS__)
#define QDHLog(pChr,...) QHLog(pChr,##__VA_ARGS__)
#define QDCmt(pChr,...)  QCmt(pChr,##__VA_ARGS__)
#define QDEMark(pChr,...) QEMark(pChr,##__VA_ARGS__)

#define QDALog(action, pchar, ...) QALog(action, pchar, ##__VA_ARGS__)
#define QADErr(action, pchar, ...) QAErr(action,pchar, ##__VA_ARGS__)
#define QADWarn(action, pChr,...)  QAWarn(action,pChr,##__VA_ARGS__)
#define QADInfo(action, pChr,...)  QAInfo(action,pChr,##__VA_ARGS__)
#define QADMark(action, pChr,...)  QAMark(action,pChr,##__VA_ARGS__)
#define QADHLog(action, pChr,...)  QAHLog(action,pChr,##__VA_ARGS__)
#define QADCmt(action, pChr,...)   QACmt(action,pChr,##__VA_ARGS__)
#define QADEMark(action, pChr,...) QAEMark(action,pChr,##__VA_ARGS__)

#else
#define QDLog(pchar, ...)
#define QDWarn(pChr,...)
#define QDErr(pchar, ...)
#define QDInfo(pChr,...)
#define QDMark(pChr,...)
#define QDHLog(pChr,...)
#define QDCmt(pChr,...)
#define QDEMark(pChr,...)

#define QDALog(action, pchar, ...)
#define QADErr(action, pchar, ...)
#define QADWarn(action, pChr,...)
#define QADInfo(action, pChr,...)
#define QADMark(action, pChr,...)
#define QADHLog(action, pChr,...)
#define QADCmt(action, pChr,...)
#define QADEMark(action, pChr,...)

#endif

#ifdef DEBUG
#define QDLogR(pchar, ...) QLogR(pchar, ##__VA_ARGS__)
#define QDWarnR(pChr,...) QWarnR(pChr,##__VA_ARGS__)
#define QDInfoR(pChr,...) QInfoR(pChr,##__VA_ARGS__)
#define QDMarkR(pChr,...) QMarkR(pChr,##__VA_ARGS__)
#define QDHLogR(pChr,...) QHLogR(pChr,##__VA_ARGS__)
#define QDCmtR(pChr,...)  QCmtR(pChr,##__VA_ARGS__)
#define QDEMarkR(pChr,...) QEMarkR(pChr,##__VA_ARGS__)
#else
#define QDLogR(pchar, ...)
#define QDWarnR(pChr,...)
#define QDInfoR(pChr,...)
#define QDMarkR(pChr,...)
#define QDHLogR(pChr,...)
#define QDCmtR(pChr,...)
#define QDEMarkR(pChr,...)
#endif

}

#endif //JSONPROTOCOL_QLOGGER_H
