//
// Created by Lenn on 2025/10/23.
//

#ifndef TOUCHSENSOR_DLOG_HH
#define TOUCHSENSOR_DLOG_HH

#include <vector>
#include <chrono>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/daily_file_sink.h>
#include <spdlog/async.h>
#include <spdlog/sinks/stdout_color_sinks.h>

#ifndef SPDLOG_TRACE_ON
#define SPDLOG_TRACE_ON
#endif

#ifndef SPDLOG_DEBUG_ON
#define SPDLOG_DEBUG_ON
#endif

// #define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE

enum class DLogLevel {
    TRACE,
    DEBUG,
    INFO,
    WARN,
    ERR,
    CRITICAL,
    OFF
};

class  DLog{

public:
    static DLog* get_instance() {
        static DLog dlogger;
        return &dlogger;
    }

    std::shared_ptr<spdlog::logger> get_logger() {
        return log_;
    }

    static void set_level(DLogLevel level);
private:
    DLog() {
        std::vector<spdlog::sink_ptr> sinks;
        auto consolesink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
        consolesink->set_level(level_);
        consolesink->set_pattern("[%Y-%m-%d %H:%M:%S.%e][thread %t][%@,%!][%l] : %v");
        sinks.push_back(consolesink);

        auto dailysink = std::make_shared<spdlog::sinks::daily_file_format_sink_mt>("logs/daily.log", 23, 59);
        dailysink->set_level(level_);
        dailysink->set_pattern("[%Y-%m-%d %H:%M:%S.%e][thread %t][%@,%!][%l] : %v");
        sinks.push_back(dailysink);

        log_ = std::make_shared<spdlog::logger>("both", std::begin(sinks), std::end(sinks));
        spdlog::register_logger(log_);
        // spdlog::flush_every(std::chrono::seconds(1));
        spdlog::flush_every(std::chrono::seconds(1));
    }

    ~DLog() = default;
    std::shared_ptr<spdlog::logger> log_;
    static spdlog::level::level_enum level_;
};


#define LogTrace(...) SPDLOG_LOGGER_CALL(DLog::get_instance()->get_logger().get(), spdlog::level::trace, __VA_ARGS__);
#define LogDebug(...) SPDLOG_LOGGER_CALL(DLog::get_instance()->get_logger().get(), spdlog::level::debug, __VA_ARGS__);
#define LogInfo(...) SPDLOG_LOGGER_CALL(DLog::get_instance()->get_logger().get(), spdlog::level::info, __VA_ARGS__);
#define LogWarn(...) SPDLOG_LOGGER_CALL(DLog::get_instance()->get_logger().get(), spdlog::level::warn, __VA_ARGS__);
#define LogErr(...) SPDLOG_LOGGER_CALL(DLog::get_instance()->get_logger().get(), spdlog::level::err, __VA_ARGS__);
#define LogCritical(...) SPDLOG_LOGGER_CALL(DLog::get_instance()->get_logger().get(), spdlog::level::critical, __VA_ARGS__);
#define LogOff(...) SPDLOG_LOGGER_CALL(DLog::get_instance()->get_logger().get(), spdlog::level::off, __VA_ARGS__);

#endif //TOUCHSENSOR_DLOG_HH
