#ifndef _EXCEPTION_H_INCLUDED_ 
#define _EXCEPTION_H_INCLUDED_ 
/////////////////////////////////////////////////////////////////////////////// 
//                                                         
// Exception.h 
// ----------- 
// Exception class definition 
//                                                         
// Design and Implementation by Bjoern Lemke               
//                                                         
// (C)opyright 2000-2016 Bjoern Lemke
// 
// INTERFACE MODULE 
// 
// Class: Exception
// 
// Description: Exception manager class
// 
// Status: CLEAN
//
/////////////////////////////////////////////////////////////////////////////// 

#include <stdio.h> 

// BASE INCLUDES 
#include "StackT.h" 
#include "Chain.h" 

#define EXLOC Chain(__FILE__), __LINE__ 

class Exception { 

public: 

    Exception(const Chain& module, int line, const Chain& msg) 
    { 
        ExcepStruct ms; 
        ms._msg = msg; 
        ms._line = line; 
        ms._module = module; 
        _excepStack.Push(ms); 
	
	_baseMsg = msg;
    } 
    
    Exception(const Chain& module, int line, const Chain& msg, Exception e) 
    { 
        _excepStack = e._excepStack; 
        
        ExcepStruct es; 
        es._msg = msg; 
        es._line = line; 
        es._module = module; 

        _excepStack.Push(es); 
        
	_baseMsg = e._baseMsg;
    } 
    ~Exception() 
    { 
        _excepStack.Empty(); 
    } 

    bool pop(Chain& module, int& line, Chain& msg)
    {
	
	ExcepStruct es; 
        if ( _excepStack.Pop(es) )
	{
	    module = es._module;
	    line = es._line;
	    msg = es._msg;
	    return true;
	}
	else
	{
	    return false;
	}
	    
    }

    bool pop(Chain& msg)
    {
	
	ExcepStruct es; 
        if ( _excepStack.Pop(es) )
	{
	    msg = es._msg;
	    return true;
	}
	else
	{
	    return false;
	}   
    }

    void print() 
    { 
	ExcepStruct es; 
        while (_excepStack.Pop(es) ) 
        { 
            cout << es._module << " ( Line " << es._line << " ) : " << es._msg << endl; 
        }
    } 

    Exception& operator = (const Exception& e) 
    { 
        _excepStack = e._excepStack; 
	_baseMsg = e._baseMsg;
        return (*this); 
    } 

    const Chain& getBaseMsg()
    {
	return _baseMsg;
    }
    
private: 
    
    class ExcepStruct {
    public:

	ExcepStruct() {};
	~ExcepStruct() {};
	ExcepStruct& operator = (const ExcepStruct& es)  { 
	    _msg = es._msg;
	    _module = es._module;
	    _line = es._line;
	    return (*this); 
	}
        Chain _msg; 
        Chain _module; 
        int _line;
	
    };   
    StackT<ExcepStruct> _excepStack; 

    Chain _baseMsg;
};
#endif
