#pragma once
#include <iostream>
#include <sstream>
#include <string>
//#pragma warning(disable:4251)

#define PRINT_TERMINAL(f,l,s)  printf("%s(%d) - %s\n", f, l, s);

namespace log4cplus
{
    class Logger;
}
//class LogStream;

#define OPEN_DEBUG_LOG LogStream::OpenDebugLog(true);

#define PRINT_DEBUG(fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Debug, __FILE__, __LINE__, "")\
         << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define PRINT_INFO(fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Info, __FILE__, __LINE__, "")\
         << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define PRINT_WARN(fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Warn, __FILE__, __LINE__, "")\
         << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define PRINT_ERROR(fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Error, __FILE__, __LINE__, "")\
         << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define PRINT_FATAL(fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Fatal, __FILE__, __LINE__, "")\
         << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}

#define LOG_DEBUG(id,fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Debug, __FILE__, __LINE__, "")\
         << "ErrorId("<< id << ") " << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define LOG_INFO(id,fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Info, __FILE__, __LINE__, "")\
         << "ErrorId("<< id << ") " << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define LOG_WARN(id,fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Warn, __FILE__, __LINE__, "")\
         << "ErrorId("<< id << ") " << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define LOG_ERROR(id,fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Error, __FILE__, __LINE__, "")\
         << "ErrorId("<< id << ") " << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}
#define LOG_FATAL(id,fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Fatal, __FILE__, __LINE__, "")\
         << "ErrorId("<< id << ") " << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
}

#define LOG_ERROR_RETURN(id,fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Error, __FILE__, __LINE__, "")\
         << "ErrorId("<< id << ") " << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
    return id;\
}
#define LOG_FATAL_RETURN(id,fmt,...) {\
    char buffer[1024];\
	snprintf(buffer, 1024, fmt, __VA_ARGS__);\
    LogStream(LogStream::LogLevel::Fatal, __FILE__, __LINE__, "")\
         << "ErrorId("<< id << ") " << buffer; \
    PRINT_TERMINAL( __FILE__, __LINE__,buffer); \
    return id;\
}

#define LogInfo LogStream(LogStream::LogLevel::Info, __FILE__, __LINE__, __FUNCTION__)
#define LogError LogStream(LogStream::LogLevel::Error, __FILE__, __LINE__, __FUNCTION__)
#define LogWarn LogStream(LogStream::LogLevel::Warn, __FILE__, __LINE__, __FUNCTION__)
#define LogDebug LogStream(LogStream::LogLevel::Debug, __FILE__, __LINE__, __FUNCTION__)
#define LogFatal LogStream(LogStream::LogLevel::Fatal, __FILE__, __LINE__, __FUNCTION__)

//����ģ����־�����LogInfoP("ModeName","DirName") << "hahahahahahhahaha";
//����ModeNameΪ�������ɵ���־�ļ�����, DirNameΪ��־�ļ�д����ļ���
#define LogInfoP(moduleName, pathName) LogStream(moduleName, pathName,LogStream::LogLevel::Info, __FILE__, __LINE__, __FUNCTION__)
#define LogErrorP(moduleName, pathName) LogStream(moduleName, pathName,LogStream::LogLevel::Error, __FILE__, __LINE__, __FUNCTION__)
#define LogWarnP(moduleName, pathName) LogStream(moduleName, pathName,LogStream::LogLevel::Warn, __FILE__, __LINE__, __FUNCTION__)
#define LogDebugP(moduleName, pathName) LogStream(moduleName, pathName,LogStream::LogLevel::Debug, __FILE__, __LINE__, __FUNCTION__)
#define LogFatalP(moduleName, pathName) LogStream(moduleName, pathName,LogStream::LogLevel::Fatal, __FILE__, __LINE__, __FUNCTION__)


//
class SBTLogger;
class __declspec(dllexport) LogStream {
public:
    enum LogLevel
    {
        Info,
        Error,
        Warn,
        Debug,
        Fatal,
    };

    static void OpenDebugLog(bool bOpen);

    LogStream(LogLevel level, const char* file, int line, const char* function, bool clean = false);

    LogStream(const std::string& moduleName, const std::string& pathName, LogLevel level, const char* file, int line, const char* function, bool clean = false);
    template<typename T>
    LogStream& operator<<(const T& message) {
        ss << message;
        return *this;
    }

    ~LogStream();

private:
    //log4cplus::Logger &logger;
    //log4cplus::Logger moduleLogger;
    bool isModule = false;
    LogLevel m_level;
    const char* file;
    int line;
    const char* function;
    std::ostringstream ss;
    bool clean;
    std::string m_moduleName = "";
    std::string m_pathName = "";
};