
//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

namespace mudbox {
/// \brief Holds information about an error. Typically heap allocated.
/// 
/// Objects of this class are usually created on the heap
/// and used in exception handling in the following way:
/// \code
/// try
/// {
///     MyFunction();
/// }
/// catch( Error *pError )
/// {
///    // report the error to the user, and delete the object.
///    pError->Report();
///    ... do something here to handle the problem
/// }
/// \endcode
/// In MyFunction somewhere you can write:
/// \code
/// ...
/// if ( pPointer == 0 )
///     throw new Error( "No object specified" );
/// ...
/// \endcode
/// You should use the #MB_ERROR macro to throw Errors:
/// \code
/// MB_ERROR( "No pointer specified in step %d", iStep );
/// \endcode
/// See the macro #MB_ERROR for more details.
class MBDLL_DECL Error
{
	QString m_sErrorMessage;
	bool m_bOnHeap;
	const char *m_pFunction, *m_pSource;
	unsigned int m_iLine;

public:
	enum Code
	{
		codeOk,
		codeOutOfMemory,
		codeHardwareFailure,
		codeOutOfVideoMemory,
		codeUnspecified
	} m_eCode;

private:
	Error( const QString &sMessage, bool bOnHeap, Code eCode = codeUnspecified );

public:
	/// \brief Constructor.
	///
	/// How this is usually used:
	/// \code
	/// throw new Error( "Some message" );
	/// \endcode
	Error(
		const QString &sMessage,				///< [in] Message that explains the error
		Code eCode = codeUnspecified,		///< [in] Error code (optional)
		const char *pFunction = 0,			///< [in] Name of the function where the error happens (optional)
		const char *pSourceFileName = 0,	///< [in] Name of the source files where the error happens (optional)
		unsigned int iLine = 0				///< [in] Line number in the source file where the error happens (optional)
		);

	/// \brief Sets the message in the error using printf-like formatting.  Returns a pointer to itself.
	///
	/// Call this method with the same arugments you would use for printf.
	Error *Format( const char *pMessage, ... );

	/// Returns the error code associated with the error.
	enum Code Code( void ) const;

	/// Returns the error message associated with the error.
	const QString &Message( void ) const;

	/// \brief Reports the error to the user in a message box and deletes the Error object.
	///
	/// Errors are written into the log file, and also reported in a message box that the user must
	/// dismiss.  If you specify a pretext string, it will be displayed first.  After reporting is
	/// complete, the Error object will be deleted in this call (except s_cBadAlloc errors, which
	/// don't reside in deletable space.)
	void Report(
		const QString &sPre = ""		///< [in] Optional string describing the pretext of the error
		) const;

	/// Discards the error message and deletes the object (except s_cBadAlloc errors, which should never be deleted.)
	void Discard( void ) const;

	/// Throws a static bad alloc exception.  (No memory allocation is required to report allocation problems.)
	static void ThrowBadAlloc( void ) { throw &s_cBadAlloc; };

	static Error s_cBadAlloc;
};

}; // end of namespace mudbox

