#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <time.h>
#include <chrono>
#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/stdout_color_sinks.h" // or "../stdout_sinks.h" if no color needed
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"

#ifdef _WIN32
#define LOGGER_API __declspec(dllexport)
#else
#define LOGGER_API  __attribute__ ((visibility("default")))
#endif

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif


//默认的日志输出格式
#define LOG_OUTPUT_FORMAT_ALL      "%^[ %Y-%m-%d %H:%M:%S.%e ] <thread %t> [%n] [%l]\n%@,%!\n%v%$\n"
#define LOG_OUTPUT_FORMAT_SIMPLE      "[%n][%l] [%H:%M:%S.%e] [%s:%#]: %v"
#define LOG_OUTPUT_FORMAT_NONE      "%v" 
#define LOG_OUTPUT_FORMAT_NONE_10KG      "[%H:%M]: %v"

// 日志类型
typedef enum tagLogType
{
    _DEFAULT,    //默认日志（以程序执行时刻日期命名）
    _TIMER,      //耗时日志，循环日志，仅打印耗时信息
    _INPUT,      //输入日志（循环日志，保持常开）
    _OUTPUT,     //输出日志（循环日志，保持常开）
}LogType;


class LOGGER_API XLogger
{

public:
    static XLogger* getInstance();

    // 获取日志对象
    std::shared_ptr<spdlog::logger> getLogger(LogType type = LogType::_DEFAULT);

    // 设置日志输出级别
    void setLevel(LogType type, int lev);

    // 设置所有日志输出级别
    void setLevel(int lev);


    // 查询日志级别
    int getLevel(LogType type = LogType::_DEFAULT);

    // 通过文件设置默认日志级别
    void setLevelByFileState();

    // 创建所有日志
    void createAllLogger();

    bool fileState;     // 日志等级为文件设置状态
    std::string log_dir; //日志输出路径

private:
    // make constructor private to avoid outside instance

    XLogger();
    ~XLogger();

    XLogger(const XLogger&) = delete;
    XLogger& operator=(const XLogger&) = delete;

private:

    std::shared_ptr<spdlog::logger> m_logger;       //基本日志
    std::shared_ptr<spdlog::logger> m_logger_Timer;  //耗时统计日志
    std::shared_ptr<spdlog::logger> m_logger_in;    //输入日志
    std::shared_ptr<spdlog::logger> m_logger_out;   //输出日志

    // 使用文件控制输出日志级别
    int getFileCtrlLevel();

};


// LOG API
#define LOG_TRACE(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::trace, __VA_ARGS__)
#define LOG_DEBUG(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::debug, __VA_ARGS__)
#define LOG_INFO(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::info, __VA_ARGS__)
#define LOG_WARN(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::warn, __VA_ARGS__)
#define LOG_ERROR(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger().get(), spdlog::level::err, __VA_ARGS__)

#define LOG_TIME(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger(LogType::_TIMER).get(), spdlog::level::debug, __VA_ARGS__)
#define LOG_DEBUG_INPUT(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger(LogType::_INPUT).get(), spdlog::level::debug, __VA_ARGS__)
#define LOG_DEBUG_OUTPUT(...) SPDLOG_LOGGER_CALL(XLogger::getInstance()->getLogger(LogType::_OUTPUT).get(), spdlog::level::debug, __VA_ARGS__)




 //设置所有日志级别
#define LOG_SETLEVEL(level) (XLogger::getInstance()->setLevel(level))
#define LOG_SETLEVELBYFILE() (XLogger::getInstance()->setLevelByFileState())

#define LOG_GETLEVEL() (XLogger::getInstance()->getLevel())
#define LOG_GETFILESTATE() (XLogger::getInstance()->fileState)





#ifdef _MSC_VER
#pragma warning(pop)
#endif

