/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkDebugManager.h
	Version:		$Revision: 1817 $
	Date:			$Date: 2011-09-30 16:52:28 +0200 (Fr, 30 Sep 2011) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/

#ifndef DEBUGMANAGER_H
#define DEBUGMANAGER_H

#include "ritkCore.h"

#include <QObject>
#include <QThread>
#include <QMutex>
#include <QTextStream>
#include <QDateTime>

namespace ritk
{


/**	@ingroup	Core
 *	@class		DebugManager
 *	@author		Jakob Wasza / Sebastian Bauer
 *	@brief		Class that provides basic debugging functionality
 *
 *	@details
 *	The debug manager used in the RITK. The debug manager is implemented using the 
 *	singleton design pattern. Different modes are available (atm only disabled and enabled ;) ) 
 *	for different levels of debugging. The actual debug messages has to be sent to the stream 
 *	provided by the debug manager. However, instead of using the debug manager directly for streaming 
 *	messages one should use the LOG_DEB(x) macro instead.
 *	@todo	Operator overloading for the debug manager
 */
class CORE_EXPORT DebugManager : public QObject
{
	Q_OBJECT

public:
	/// Singleton access
	static inline DebugManager& GetInstance()
	{
		static DebugManager Instance;
		return Instance;
	}


	/** @name Debugging mode */
	//@{
	/// Different debugging modes
	enum DebugModes
	{
		Disabled,
		Enabled
	};
	/// Set the current debug mode (enabled is the default)
	inline void SetDebugMode(DebugModes Mode)
	{
		m_DebugMode = Mode;
	}
	/// Get the current debug mode
	inline DebugModes GetDebugMode()
	{
		return m_DebugMode;
	}
	//@}

	/// Set the output stream to which debuggin information will be sent (std::cout is default)
	inline void SetOutputStream(QTextStream *stream)
	{
		m_OutputStream = stream;
	}

	/// Log a debug message
	inline void LogMessage(QString Message)
	{
		emit(LogMessageSignal(Message));
	}

public slots:
	/// For internal communication only
	void LogMessageSlot(QString Message);

signals:
	/// For internal communication only
	void LogMessageSignal(QString Message);

	
protected:
	/// The stream on which the debugger will output log messages
	QTextStream *m_OutputStream;
	/// The debug mode
	DebugModes m_DebugMode;
	/// Mutex to lock the debug manager
	QMutex m_Mutex;

private:
	/// Private constructor
	DebugManager();
	/// Private destructor
	~DebugManager();
	/// Prevent copy-construction	
	DebugManager(const DebugManager&);    
	/// Prevent assignment
	DebugManager& operator=(const DebugManager&); 
};


} // end namespace ritk

/// @name Operator overloading that is not provided by default
//@{
CORE_EXPORT QTextStream& operator<<(QTextStream& out, std::string &s);
CORE_EXPORT QTextStream& operator<<(QTextStream& out, std::exception &e);
//@}

/**	@brief	Macro for logging debug messages
 *
 *	@details
 *	Usage is like LOG_DEB("Log message1 " << "variable=" << some_variable), streams are supported
 */
#define LOG_DEB(x)																				\
{																								\
	if ( ritk::DebugManager::GetInstance().GetDebugMode() != ritk::DebugManager::Disabled )		\
	{																							\
		QString LogString;																		\
		QTextStream LogStream(&LogString);														\
		QDateTime DT = QDateTime::currentDateTime();											\
		LogStream << "[" << DT.toString("dd.MM.yyyy hh:mm:ss.zzz") << "] " << x << "\n";		\
		LogStream << " " << __FILE__ << " Line " << __LINE__ << "\n";							\
		LogStream << "\n";																		\
		ritk::DebugManager::GetInstance().LogMessage(*LogStream.string());						\
	}																							\
}



#endif // DEBUGMANAGER_H
