#ifndef LOGGER_H_
#define LOGGER_H_

#include <fstream>
#include <sstream>
#include <map>
#include <string>

#include "config.h"

//DEBUG < INFO < WARN < ERROR < FATAL < NONE
#define LOG_DEBUG	0
#define LOG_INFO	1
#define LOG_WARN	2
#define LOG_ERROR	3
#define LOG_FATAL	4
#define LOG_NONE	5

#define _DEBUG(msg)	{\
	if (Logger::getLevel() == LOG_DEBUG) Logger::_oss << "DEBUG " << __PRETTY_FUNCTION__ << ":" << __LINE__ << " ";\
	Logger::_oss << msg;\
	Logger::getInstance()->log(LOG_DEBUG);\
};

#define _INFO(msg)	{\
	if (Logger::getLevel() == LOG_DEBUG) Logger::_oss << "INFO " << __PRETTY_FUNCTION__ << ":" << __LINE__ << " ";\
	Logger::_oss << msg;\
	Logger::getInstance()->log(LOG_INFO);\
};

#define _WARN(msg)	{\
	if (Logger::getLevel() == LOG_DEBUG) Logger::_oss << "WARNING " << __PRETTY_FUNCTION__ << ":" << __LINE__ << " ";\
	Logger::_oss << msg;\
	Logger::getInstance()->log(LOG_WARN);\
};

#define _ERROR(msg)	{\
	if (Logger::getLevel() == LOG_DEBUG) Logger::_oss << "ERROR " << __PRETTY_FUNCTION__ << ":" << __LINE__ << " ";\
	Logger::_oss << msg;\
	Logger::getInstance()->log(LOG_ERROR);\
};

#define _FATAL(msg)	{\
	if (Logger::getLevel() == LOG_DEBUG) Logger::_oss << "FATAL ERROR " << __PRETTY_FUNCTION__ << ":" << __LINE__ << " ";\
	Logger::_oss << msg;\
	Logger::getInstance()->log(LOG_FATAL);\
};

class Logger
{
public:
	virtual ~Logger();
	
	/** Singleton instantiator */
	static Logger* getInstance();
	/** Sets the filename of the file to log to */
	static void setFilename(std::string filename) { _filename = filename; };
	/** Sets the threshhold level for messages to be logged */
	static void setLevel(int level) { if (level >= LOG_DEBUG && level <= LOG_FATAL) _level = level; };
	static int getLevel() { return _level; };
	
	/** Logs a message with set severity. The message is to be passed to the Logger::_oss object */
	void log(int severity);
	
	/** The object to pass the message to */
	static std::ostringstream _oss;

private:
	/** The only Logger instance (is a singleton) */
	static Logger* _instance;
	/** Filename of the log file */
	static std::string _filename;
	/** Default logging threshhold */
	static int _level;
	/** Log file deskriptor */
	std::ofstream _file;
	
	Logger();
	Logger(const Logger&);
	Logger& operator=(const Logger&);
};

#endif /*LOGGER_H_*/
