#ifndef LHLOG_FILE_SINK_H
#define LHLOG_FILE_SINK_H

/**
 * @file LHLog_file_sink.h 
 * @author your name (you@domain.com)
 * @brief 自定义的日志输出管道,输出到LHQLog中,由他写入文件
 * @version 0.1
 * @date 2024-07-18
 * 
 * @copyright Copyright (c) 2024
 * 
 */

#include "spdlog/common.h"
#include "spdlog/details/log_msg.h"
#include "spdlog/details/synchronous_factory.h"
#include "spdlog/sinks/base_sink.h"
#include <array>
#include "LHQLogAPI.h"

#include <QString>
#include <QDebug>

namespace spdlog {
namespace sinks {

template<typename Mutex>
class LHLog_file_sink : public base_sink<Mutex>
{
public:
    /**
     * @brief Construct a new lhlog file sink object
     * 
     * @param lhLog LHLog实例
     * @param labName 需要加载的库名
     * @param strLogName 日志模块名称
     */
    LHLog_file_sink(CLHQLogApi* lhLog, QString labName, QString strLogName) : 
        m_lhLog(lhLog),
        m_libName(labName),
        m_strLogName(strLogName)
    {
        if(m_lhLog != nullptr)
        {
            m_lhLog->Load(labName);
            m_lhLog->DoInitial(strLogName);
        }
    }
    ~LHLog_file_sink() override = default;

protected:
    /* 关键函数,从这里获取数据 */
    void sink_it_(const details::log_msg &msg) override {

        /* 获取输出等级 */
        level::level_enum msgLevel = msg.level;

        /* 内存中的数据 */
        memory_buf_t formatted;
        /* 从msg原始数据经过变换,处理通配符相关的东西,好像是处理啥指针问题? */
        base_sink<Mutex>::formatter_->format(msg, formatted);
        /* 去掉结尾的换行符 */
        auto size = formatted.size();
        // qDebug() << "formatted.size() = " << formatted.size();
        if(size >= 2 && ( formatted[size - 1] == '\n' ) && ( formatted[size - 2] == '\r') )
        {
            formatted.resize(size - 2);
        }
        else if(size >= 1 && (formatted[size - 1] == '\n' || formatted[size - 1] == '\r'))
        {
            formatted.resize(size - 1);
        }
        /* 添加\0,QString以这个为结尾 */
        formatted.push_back('\0');
        
        /* 这个应该是处理兼容性的问题,C++17以前的兼容性问题
        *  这个可以提供对字符串的快速访问,不需要拷贝字符串 */
        const string_view_t str = string_view_t(formatted.data(), formatted.size());
        // qDebug() << "Aftter string_view_t formatted.size() = " << formatted.size();
        /* 根据等级输出 */
        if(msgLevel == level::trace) {
            /* 这个等级不输出,理论上也不会有这个等级的日志到这一步,在外面就拦截了 */
            
        }
        else if (msgLevel == level::debug) {
            m_lhLog->DoWriteLogEx(m_strLogName, ELT_Log_Debug, str.data());
        }
        else if (msgLevel == level::info) {
            m_lhLog->DoWriteLogEx(m_strLogName, ELT_Log_Common, str.data());
        }
        else if(msgLevel == level::warn) {
            m_lhLog->DoWriteLogEx(m_strLogName, ELT_Log_Error, str.data());
        }
        else if (msgLevel == level::err) {
            m_lhLog->DoWriteLogEx(m_strLogName, ELT_Log_Error, str.data());
        }
        else if(msgLevel == level::critical) {
            /* 因该不会用到这个等级,不输出 */
            
        }else if (msgLevel == level::off) {
            /* 不输出 */
        
        }

        // QString strLog = QString::fromLocal8Bit(str.data(), str.size());
        
        // qDebug() << strLog;
    }

    void flush_() override {}

private:
    CLHQLogApi* m_lhLog = nullptr;
    QString m_strLogName;
    QString m_libName;
};

using LHLog_file_sink_mt = LHLog_file_sink<std::mutex>;
using LHLog_file_sink_st = LHLog_file_sink<details::null_mutex>;

} // namespace sinks
} // namespace spdlog


#endif /* LHLOG_FILE_SINK_H */