/*************************************************************************************************
** Project:     FSMGenerator
** Package:     FSMApi
** Module:      FSMApi::Cpp
** File:        FSM.h
** Date:        2002.08.01
** Author:      Pavel Bekkerman (chpavel@tx.technion.ac.il)
** Copyright:   Copyright (C) 2002 Pavel Bekkerman
** License:
**              This program is free software; you can redistribute it and/or
**              modify it under the terms of the GNU 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 General Public License for more details.
**
**              You should have received a copy of the GNU 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.
**
** Contact:     Pavel Bekkerman (chpavel@tx.technion.ac.il)
*************************************************************************************************/

#ifndef _FSM_H
#define _FSM_H

#include "AbstractFSM.h"

namespace FSMApi
{

	class FSM
	{
	protected:
		AbstractFSM&	m_fsm;
		bool		m_bFinal;

	protected:
		int  		idStateCurrent;

	public:
		// interface
		FSM( AbstractFSM & fsm )
		: m_bFinal( false ), m_fsm( fsm )
		{
		}

		virtual ~FSM()
		{
		}

		bool IsFinal() throw() // throws FSMException
		{
			return m_bFinal;
		}

		void Initialize() throw() // throws FSMException
		{
			try
			{
				idStateCurrent = m_fsm._getStartState();
				m_fsm._processStateEnter( idStateCurrent );
				m_bFinal = m_fsm._isFinalState( idStateCurrent );
			}
			catch( FSMException& e )
			{
				throw e;
			}
		}

		void Process( int idEvent ) throw() // throws FSMException
		{
			FSMIDPair idpair;

			try
			{
				m_fsm._processEvent( idEvent );

				idpair = m_fsm._getNextIncarnation( idStateCurrent, idEvent );

				// PB: Commented out
				// Even if the next state is the current state (staying in the state), we should exit the state, take transition, and reneter the state!!!
				// if( idpair.idSecond == idStateCurrent )
				// return;

				m_fsm._processStateExit( idStateCurrent );
				m_fsm._processTransition( idpair.idFirst );

				idStateCurrent = idpair.idSecond;
				m_fsm._processStateEnter( idStateCurrent );
				m_bFinal = m_fsm._isFinalState( idStateCurrent );
			}
			catch( FSMException& e )
			{
				throw e;
			}
		}

		void Attach( FSM fsm ) throw() // throws FSMException
		{
		}

		void Finalize() throw() // throws FSMException
		{
		}

	}; // class 

} // namespace FSMGenerator

#endif // _FSM_H

