#ifndef __LOG_H
#define __LOG_H
//It is bad to include files within other include files, but this is an exception to simplify the code
#include <stdio.h>

//must be put in global scope and used once in all files
#define LOG_DECLARE Log __log__;
//used in any file need to access the log files, except the file that has LOG_DECLARE statment
#define LOG_USE(); extern Log __log__;
//init log files, called once in program initialization
#define LOG_INIT(fileName) do{if(fileName!= NULL)__log__.init(fileName); else printf("error init log file %s", fileName);}while(0);
#define LOG_INIT_OVERWRITE(fileName) do{if(fileName!= NULL)__log__.init_overwrite(fileName); else printf("error init log file %s", fileName);}while(0);

//here are the different levels of logging
#define LOG_VERBOSE(msg) __log__.write("verbose", msg, __FILE__, __LINE__); //detaild info
#define LOG_MSG(msg) __log__.write_brief(msg); //brief info
#define LOG_WARN(msg) __log__.write("warn", msg, __FILE__, __LINE__); //warning
#define LOG_ERR(msg) __log__.write("error", msg, __FILE__, __LINE__); //error
#define LOG_FATAL(msg) __log__.write("fatal", msg, __FILE__, __LINE__); //fatal error
#define LOG_CLOSE __log__.close();

class Log
{
	FILE *fp;
	bool logOk;

	public:

	Log()
	{fp = NULL;}
	~Log() //the destructor closes the file
	{close();}

	void init(const char *pfileName)
	{ if(pfileName != NULL) {fp = fopen(pfileName, "a+"); if(fp != NULL) fseek(fp, 0, SEEK_END);} }
	
	void init_overwrite(const char *pfileName)
	{ if(pfileName != NULL) {fp = fopen(pfileName, "w");}  }

	void close()
	{if(fp != NULL) fclose(fp); fp = NULL;}

	//FIXME: A critical section is required to protect the file writing function in multithreading programms
	void write(const char *pType, const char *pMsg, const char *pFileName, int lineNo)
	{
		if(fp != NULL) fprintf(fp, "%s\t%s\t%s\t%s\t%d\t%s\n", pType, __DATE__, __TIME__, pFileName, lineNo, pMsg); 
	}
	
	void write_brief(const char *pMsg)
	{ 
		if(fp != NULL) fprintf(fp, "%s", pMsg); 
	}
};

#endif
