#pragma once
#include "export_log_impl.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <memory>
#include <thread>
#include <atomic>
#include <deque>
#include <mutex>
#include <map>
#include <chrono>
#include <corecrt_io.h>
#include <qdebug.h>
#include "clog.h"

namespace lp {
	typedef std::pair<std::string, std::shared_ptr<std::ofstream>> pair_file_ofs;
	typedef std::pair<std::string, std::string> pair_filed_log;

	struct stLogError :public ILogST {
		stLogError() :ILogST(lp::kError) { *this << " [E] "; }
	};
	struct stLogDebug :public ILogST {
		stLogDebug() :ILogST(lp::kDebug) { *this << " [D] "; }
	};
	struct stLogInfo :public ILogST {
		stLogInfo() :ILogST(lp::kInfo) { *this << " [I] "; }
	};
	struct stLogWarn:public ILogST {
		stLogWarn() :ILogST(lp::kWarn) { *this << " [W] "; }
	};

	struct stLogTrace :public ILogST {
		stLogTrace() :ILogST(lp::kFatal) { *this << " [F] "; }
	};

	class LOG_IMPL_EXPORT FileLogger: public lp::ILogger {
	private:
		std::thread             m_trdTask;
		std::mutex              m_lkTask;
		std::atomic<bool>       m_bExit;
		std::deque<pair_filed_log> m_deqLogs;
		std::deque<pair_filed_log> m_deqLogsWrite;
		std::condition_variable m_condTask;
		std::map<std::string, pair_file_ofs> m_ofsMapStream;
	private:
		bool m_bOpenLog;
		int  m_nSaveDay;
		int  m_nSegmentSize;
		ELogType m_eLogType = ELogType::kInfo;
	public:
		virtual bool Init(bool bOpenLog, int nSaveDay, int nSegmentSize) override;
		virtual bool UnInit() override;
		virtual void AddLog(ELogType type, const std::string& info) override;
		void AddLog(ELogType type, const std::string& info, const char* sFile, int iLine) override;
		void AddLog(ILogST& stLog, const std::string& moduleName, 
					const std::string& sFileName, int line, EWriteMode eWritype = kAsync) override;

		void AddLog(const std::string& info, const std::string& moduleName) override;

		void SetLogLevel(ELogType eType) override;

	private:
		/*!
		* 打开日志
		*
		* \return
		*/
		bool OpenLog(pair_file_ofs& spOfs, std::string moduleName);
		/*!
		* 关闭日志
		*
		* \return
		*/
		bool CloseLog();
		/*!
		* 关闭日志
		*
		* \return
		*/
		bool CloseLog(std::shared_ptr<std::ofstream>& spOfs);
		/*!
		* 写日志
		*
		* \param size
		*/
		void WriteLog(std::deque<pair_filed_log>& deqLogs);
		/*!
		* 写日志
		*
		* \param stLog
		*/
		void WriteLog(std::ostringstream& stLog, const std::string& name, int line, const std::string& modefiled);
		/*!
		* 检查并分割日志
		*
		* \return
		*/
		bool CheckSegmentFile();
		/*!
		* 检查并清理日志
		*
		* \return
		*/
		bool CheckClearFile();
		/*!
		* 启动异步日志
		*
		*/
		void StartAnsyLog();
		/*!
		* 刷新日志
		*
		*/
		void Flush();
		/*!
		* 刷新日志
		*
		*/
		void Flush(std::shared_ptr<std::ofstream>& spOfs);
		/*!
		* 取得文件名
		*
		*/
		inline std::string GetFileName(const std::string& filepath);
	public:
		FileLogger();
		virtual ~FileLogger();
	};
}