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

namespace DESpot
{
	class DesStateIterator : public Iterator<DesState&, const DesState&>
	{
		public:
			DesStateIterator(const std::vector<DesState*>& statePool): m_statePool(statePool)
			{
			}
			
			virtual ~DesStateIterator(void) 
			{
			}
		
		public:
			virtual void first() const 
			{
				//start with the first element and increment until we find the first non-null element
				m_crtStateIt = m_statePool.begin();
				while((m_crtStateIt != m_statePool.end()) && (*m_crtStateIt == null))
				{
					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 element or we reach the end
				while((m_crtStateIt != m_statePool.end()) && (*m_crtStateIt == null))
				{
					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
			DesStateIterator(const DesStateIterator& other) : m_statePool(other.m_statePool){}
                        DesStateIterator& operator= (const DesStateIterator&) {return *this; }

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


	};
} //end of namespace DESpot
