/*
 * This source file is part of KEOS (Free 3D Engine)
 * For the latest info, see http://www.keosengine.org/
 * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * 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 the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
 * http://www.gnu.org/copyleft/lesser.txt.
 *
 */

#ifndef KEOS_EXCEPTION_H
#define KEOS_EXCEPTION_H

#include "KeosPrerequisites.h"

#define BADDELETE_EXCEPT(p, f, l, a)    {Keos::CBadDelete except((p), (f), (l), (a)); LOG_TMP}
#define LOADINGFAILED_EXCEPT(f, m, s)   {Keos::CLoadingFailed except((f), (m), (s)); LOG_TMP}
#define DYNLIB_EXCEPT(f, m, s)          {Keos::CDynLibError except((f), (m), (s)); LOG_TMP}
#define OUTOFMEMORY_EXCEPT( m, s)       {Keos::COutOfMemory except((m), (s)); LOG_TMP}
#define UNSUPPORTED_EXCEPT( m, s)       {Keos::CUnsupported except((m), (s)); LOG_TMP}
#define BADCONVERSION_EXCEPT( m, s)     {Keos::CBadConversion except((m), (s)); LOG_TMP}

#define LOG_TMP except.SetFileLine(__FILE__, __LINE__); Keos::ILogger::Log("%s",except.what_short()); throw except;

namespace Keos
{
    //-----------------------------------------------------------------------
    /** Base class for the exceptions.
     *
     */
    class KEOS_EXPORT CException : public std::exception
    {
    public :

        /** Constructor.
         *  @param strMessage Message of the exception .
         */
        CException(const String& strMessage = "");

        /** Destructor.
         *  
         */
        virtual ~CException();

        /** Return the message of the exception.
         *  @return Message of the exception.
         */
        virtual const char* what() const;

        /** Return a short description of the exception.
         *  @return Short description of the exception.
         */
        const char* what_short() const;

        /** Retrieves a pointer to the last exception created.
         */
        static CException* GetLastException(void) throw();

        /** Set The file and line wher the exception occured.
         */
        void SetFileLine(String strFile, int nLine);

    protected :

        //! Message associated to the exception
        String m_strMessage;
        //! Short message for the log
        String m_strShortMessage;
        //! The last exception created
        static CException* ms_pLast;
    };


    //-----------------------------------------------------------------------
    /** Exception thrown if a condition is not verified.
     *
     */
    struct KEOS_EXPORT CAssertException : public CException
    {
        /** Constructor.
         *  @param strFile Name of the file having generated the exception.
         *  @param nLine Line in the file.
         *  @param strMessage Message of the exception.
         */
        CAssertException(const String& strFile, int nLine, const String& strMessage);
    };

    // Define Assert macro
    // allowing of generated an exception if the condition is not verified
    #ifdef KEOS_DEBUG_MODE
    #   define Assert(condition) if (!(condition)) throw CAssertException(__FILE__, __LINE__, "Unsatisfied condition\n\n" #condition)
    #else
    // In no DEBUG_MODE Assert do nothing
        inline void DoNothing(bool) {}
    #   define Assert(condition) DoNothing(!(condition))
    #endif


    //-----------------------------------------------------------------------
    /** Exception thrown during a problem of allowance memory
     *
     */
    struct KEOS_EXPORT CBadDelete : public CException
    {
        /** Constructor.
         *  @param pPtr Pointer having generated the exception.
         *  @param strFile Name of the file having generated the exception.
         *  @param nLine Line in the file.
         *  @param bNewArray The error corresponds to the allowance of an array.
         */
        CBadDelete(const void* pPtr, const String& strFile, int nLine, bool bNewArray);
    };


    //-----------------------------------------------------------------------
    /** Exception thrown during error of files loading.
     *
     */
    struct KEOS_EXPORT CLoadingFailed : public CException
    {
        /** Constructor.
         *  @param strFile Name of the file having generated the exception.
         *  @param strMessage Message of the exception.
         *  @param strSource Class and function where the exception occured.
         */
        CLoadingFailed(const String& strFile, const String& strMessage, const String& strSource);
    };

    //-----------------------------------------------------------------------
    /** Exception thrown during error of dynamic libraries loading.
     *
     */
    struct KEOS_EXPORT CDynLibError : public CException
    {
        /** Constructor.
         *  @param strFile Name of the file having generated the exception.
         *  @param strMessage Message of the exception.
         *  @param strSource Class and function where the exception occured.
         */
        CDynLibError(const String& strFile, const String& strMessage, const String& strSource);
    };


    //-----------------------------------------------------------------------
    /** Exception thrown during out of memory.
     *
     */
    struct KEOS_EXPORT COutOfMemory : public CException
    {
        /** Constructor.
         *  @param strMessage Message of the exception.
         *  @param strSource Class and function where the exception occured.
         */
        COutOfMemory(const String& strMessage, const String& strSource);
    };

    //-----------------------------------------------------------------------
    /** Exception thrown during the use of an unsupported feature.
     *
     */
    struct KEOS_EXPORT CUnsupported : public CException
    {
        /** Constructor.
         *  @param strFeature Unsupported feature name.
         *  @param strSource Class and function where the exception occured.
         */
        CUnsupported(const String& strFeature, const String& strSource);
    };

    //-----------------------------------------------------------------------
    /** Exception thrown during a conversion error.
     *
     */
    struct KEOS_EXPORT CBadConversion : public CException
    {
        /** Constructor.
         *  @param strError Error message.
         *  @param strSource Class and function where the exception occured.
         */
        CBadConversion(const String& strError, const String& strSource);
    };

} // namespace Keos

#endif // KEOS_EXCEPTION_H
