/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NLOG__
#define	__NLOG__


		#include "ntypes.h"
		#include "memory/singleton.h"
		#include "memory/nauto_ptr.h"


namespace GS {
	class String;

	namespace Threading { class	Mutex; }

		/*!
			Define the maximum log line length.
		*/
#define	LOG_LINE_MAX_LEN	8192

/*!
	@short	Log.

	The log subsystem provides several log levels to enable activation and
	deactivation of a whole log level.

	The following log streams are available to log to the different levels:

	* __LOG_H__: Header			(eg: __LOG_H__ << "Physics entry point.\n")
	* __LOG_W__: Warning
	* __LOG_E__: Error
	* __LOG_E__: Non-maskable

	Standard logs may be output to the __LOG__ stream.

	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	Log
{
protected:

		Threading::Mutex	*mutex;

#if	__PLATFORM_LOG_SUPPORT__
		char			full_a[LOG_LINE_MAX_LEN], full_b[LOG_LINE_MAX_LEN];
		char			*a, *b;
#endif

#define EngineLogNone		0						///< Log no log ouput
#define EngineLogStandard	1
#define	EngineLogHeader		2
#define	EngineLogWarning	4
#define	EngineLogError		8
#define	EngineLogVerbose	16
#define	EngineLogScript		32
#define	EngineLogAll		~0

		uint			log_level;

public:

		/// Set the log level.
		void			SetLogLevel(uint level = EngineLogAll)
		{	log_level = level;	}
		/// Get the current log level.
		uint			GetLogLevel() const
		{	return log_level;	}

		/// Get the log mutex.
		Threading::Mutex &GetMutex()
		{	return *mutex;	}

		Log				&operator << (const char);
		Log				&operator << (const short);
		Log				&operator << (const int);
		Log				&operator << (const uchar);
		Log				&operator << (const ushort);
		Log				&operator << (const uint);
	#if	__PLATFORM_IOS__
		Log				&operator << (const size_t);
	#endif
		Log				&operator << (const float);
		Log				&operator << (const bool);
		Log				&operator << (const void *);
		Log				&operator << (const char *);
		Log				&operator << (const String &);

		void			LogProcessed();

		/// Implement to receive new log lines.
virtual	void			NewLog(const char *log, char entry_level = EngineLogStandard);

		Log();
virtual	~Log();
};

/// Log system.
class	LogSystem : public Singleton <LogSystem>
{
		Log				*log;

public:

		/// Set the log object.
		void			SetLog(Log *log = 0);
		/// Get the current log object.
		Log				&GetLog();

		LogSystem();
};

//------------------------------------------------------------------------------
#define	__LOG__		GS::LogSystem::Get().GetLog()															// Standard
#define	__LOG_H__	__LOG__ << "[H] "																		// Header
#define	__LOG_CAM__	__LOG__ << "[WEBCAM] "																		// Header
#if		0
	#define	__LOG_W__	__LOG__ << "[*] " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << ") "	// Warning
	#define	__LOG_E__	__LOG__ << "[!] " << __FUNCTION__ << " (" << __FILE__ << ":" << __LINE__ << ") "	// Error
#else
	#define	__LOG_W__	__LOG__ << "[*] "
	#define	__LOG_E__	__LOG__ << "[!] "
#endif
#define	__LOG_V__	__LOG__ << "[V] "																		// Verbose
#define __LOG_F__	__LOG__ << __FUNCTION__ << ": "

#define	__LOG_FUNC__	__LOG_V__ << __FUNCTION__ << "\n";
//------------------------------------------------------------------------------

} // GS


#endif	// __NLOG__
