/*	Author: Magdin Stoica
	Supervisor: Dr. Ryan Leduc
	
	Project created in conformity with the requirements for the Degree of Master of Engineering in Software Engineering, 
	Computing and Software Department, 
	McMaster University
	2003 - 2007
*/

#pragma once

#include <map>
#include "CommonDefinitions.h"
#include "Iterator.h"
#include "DesEvent.h"


namespace DESpot
{
	class DesSelfTransIterator : public Iterator<DesEvent&, const DesEvent&>
	{
		public:

			DesSelfTransIterator(const std::map<const DesEvent::ID, const DesEvent*>& selfTransMap) 
					: m_selfTransMap(selfTransMap) 
			{
			}
			
			virtual ~DesSelfTransIterator(void)
			{
			}

		public:
			virtual void first() const 
			{
				//start with the beginning of the transition map
				m_crtSelfTransIt = m_selfTransMap.begin();				
			}

			virtual void next() const
			{
				if (m_crtSelfTransIt == m_selfTransMap.end())
				{
					assert(false);
					throw EX("Iteration already at the end. Call isDone() before calling next()")
				}

				//try to advance to the next "toState" for the current event
				m_crtSelfTransIt++;
			}
			
			virtual bool isDone() const
			{
				if (m_crtSelfTransIt == m_selfTransMap.end())
					return true;

				return false;
			}
			
			virtual DesEvent& currentItem()
			{
				if (m_crtSelfTransIt == m_selfTransMap.end())
				{
					assert(false);
					throw EX("Iterator has reached the end. Cannot return current item")
				}					
				
				const DesEvent& crtSelfTrans = *(m_crtSelfTransIt->second);
				return const_cast<DesEvent&>(crtSelfTrans);
			}

			virtual const DesEvent& currentItem() const
			{				
				if (m_crtSelfTransIt == m_selfTransMap.end())
				{
					assert(false);
					throw EX("Iterator has reached the end. Cannot return current item")
				}					
				
				return *(m_crtSelfTransIt->second);
			}

		//Implementation types
		private:
			//event id to event object map used for self-looped events
			typedef std::map<const DesEvent::ID, const DesEvent*>  SelfLoopEventMap;
			typedef SelfLoopEventMap::const_iterator SelfLoopEventIt;

		private:
			//disallow copying
			DesSelfTransIterator(const DesSelfTransIterator& other): m_selfTransMap(other.m_selfTransMap) {}
			DesSelfTransIterator& operator= (const DesSelfTransIterator&) { return *this;}

		private:
			//The self-transition map of the DesTransitionFunction (given directly by the transition function object
			//when creating the iterator
			const SelfLoopEventMap& m_selfTransMap;
			
			//current iterator through the from trans map (fromState -> event map)
			mutable SelfLoopEventIt m_crtSelfTransIt;
	};

} //end of namespace Despot

