//////////////////////////////////////////////////////////////////////////////
//  FILE       :  Log.h
//  SUBSYSTEM  :  Log
//  AUTHORS    :  Sergei V. Migdalskiy
//  REQUIRES   :
//  CONTAINS   :  Declaration of Logging Functions
//	DESCRIPTION:
//			Declares initialization of log file and logging of critical and
//      informational messages and Structured Exception dumps
//
//////////////////////////////////////////////////////////////////////////////

#ifndef __LOG_HDR__
#define __LOG_HDR__

#include <string>

#ifdef __cplusplus
extern "C" {
#endif

// call this function passing the dll or exe filepath to tell the library
// where to place the default log file. Otherwise, it will not be written
extern void InitLog (HINSTANCE);

// inits log from the exe file path; truncates the extension and changes it to Log
extern void InitLogByModuleName (const char* szExePath);
extern void SetLogPath (const char* szLogPath);

// write a string to log file
extern void VLog(const char* szFormat, va_list parameters);
extern void Log(const char* szFormat, ...);

// low-priority log
#ifdef _DEBUG
#define Log0 Log
#else
#define Log0 while (false)
#endif

#define LogStartup Log


extern void VLogSimple(const char* szFormat, va_list parameters);
extern void LogSimple(const char* szFormat, ...);
extern void VInfo(const char* szFormat, va_list parameters);
extern void Info(const char* szFormat, ...);
extern void SetInfoLevel(int nLevel);
extern void LogDisable();
extern void LogIntend (int nDelta);

#ifdef _MSC_VER
// this statement denotes the beginning of SEH-guarded block of code
#define SEH_GUARD_BEGIN __try
// this statement denotes the end of SEH - guarded block of code
#define SEH_GUARD_END(szDescription) __except (LogException(GetExceptionInformation(), szDescription))
#else
#define SEH_GUARD_BEGIN try
#define SEH_GUARD_END(szDescription) catch(...)
#endif


// this is the seen exception filter function. It receives the exception info structure and logs it.
extern int LogException (LPEXCEPTION_POINTERS pExceptionInfo, const char* szDescription);
extern int LogExceptionV (LPEXCEPTION_POINTERS pExceptionInfo, const char* szFormat, ...);

// global instance of the module in which logging takes place.
// used to log the module base address in the case of GPF(SE)
extern HINSTANCE g_hLogInst;
extern char g_szModulePath[MAX_PATH];

// sets the symbolic name of the thread
extern void LogSetThreadName (std::string sName);

// the global constant that gets set to the applicatino debug state that is only put to log if an error condition like GPF occurs
extern const char *g_szAppDbgState;

// set the debug state of the application to the given string.
// this state is only put to log if an error condition like GPF occurs
extern void DbgState(const char* sz);

// set the debug state of the application to the given string in form of printf.
// this state is only put to log if an error condition like GPF occurs
extern void DbgStateEx(const char* szFormat, ...);

// set the debug state of the application to the given string in form of vprintf.
// this state is only put to log if an error condition like GPF occurs
extern void DbgStateV(const char* szFormat, va_list params);
#define AssertRead(x) do {if (IsBadReadPtr(&(x), sizeof(x))) Log("*ERROR* Read Access Check failed for address 0x%08X size %u in file \"" __FILE__ "\" line %d timestamp " __DATE__ " " __TIME__,&(x),sizeof(x),__LINE__);}while(false)

#ifdef __cplusplus
}

// Win32 error (that is returned by GetErrorCode()) formatting into a string
// returns the string representation (in natural language) of the last error retrieved by GetLastError()
// if the error couldn't be formatted, returns a string in form "Error #NNN, couldn't format"
extern std::string FormatWinError(DWORD dwError);
// tries to format the error, if the description wasn't found, returns an empty string
extern std::string TryFormatWinError(DWORD dwError);
// converts an integer to a STL string and returns it
extern std::string IntToString (int nNumber);
// COnverts an unsigned into a hexadecimal STL string and returns it
extern std::string UIntToHexString(DWORD dwNumber);

class LogAutoIntend
{
public:
	LogAutoIntend()
	{
		LogIntend (1);
	}
	~LogAutoIntend()
	{
		LogIntend (-1);
	}
};

#define LOG_AUTO_INTEND() LogAutoIntend dummyMigdalskiyLogIntend

#endif
#endif