/*	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 <vector>
#include "CommonDefinitions.h"
#include "Iterator.h"
#include "DesState.h"

namespace DESpot
{
	class DesMarkedStateIterator : public Iterator<DesState&, const DesState&>
	{
		public:
			DesMarkedStateIterator(const std::vector<DesState*>& statePool): m_statePool(statePool)
			{
			}
			
			virtual ~DesMarkedStateIterator(void) 
			{
			}
		
		public:
			virtual void first() const 
			{
				//start with the first element and increment until we find the first non-null marked state
				m_crtStateIt = m_statePool.begin();
				while((m_crtStateIt != m_statePool.end()) && ((*m_crtStateIt == null) || ((*m_crtStateIt)->isMarked() == false)))
				{
					m_crtStateIt++;
				}
			}

			virtual void next() const
			{
				if (m_crtStateIt == m_statePool.end())
					throw EX("Iteration already at the end. Cannot go even further")

				//Advance the iterator to the next state
				m_crtStateIt++;

				//keep advancing the iterator until we find the first non-null marked state or we reach the end
				while((m_crtStateIt != m_statePool.end()) && ((*m_crtStateIt == null) || ((*m_crtStateIt)->isMarked() == false)))
				{
					m_crtStateIt++;
				}
			}
			
			virtual bool isDone() const
			{
				return m_crtStateIt == m_statePool.end();
			}
			
			virtual DesState& currentItem()
			{
				if (m_crtStateIt == m_statePool.end())
					throw EX("Iteration already at the end.  Cannot return item")
				
				const DesState& crtState = *(*m_crtStateIt);

				//To avoid to const-cast we would have need to define two interator classes like STL. This
				//much simpler
				return const_cast<DesState&>(crtState);
			}

			virtual const DesState& currentItem() const
			{
				if (m_crtStateIt == m_statePool.end())
					throw EX("Iteration already at the end.  Cannot return item")

				return *(*m_crtStateIt);
			}

			DesState::Index currentItemIndex() const
			{
				if (m_crtStateIt == m_statePool.end())
					throw EX("Iteration already at the end.  Cannot return item's index")

				return m_crtStateIt - m_statePool.begin();
			}

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

		private:
			const std::vector<DesState*>& m_statePool;
			mutable std::vector<DesState*>::const_iterator m_crtStateIt;


	};
} //end of namespace DESpot
