/*	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 "DesEvent.h"


namespace DESpot
{

	class DesEventIterator : public Iterator<DesEvent&, const DesEvent&>
	{
		public:
			DesEventIterator(const std::vector<DesEvent*>& eventPool): m_eventPool(eventPool)
			{
			}

			virtual ~DesEventIterator(void)
			{
			}

		public:
			virtual void first() const 
			{
				//start with the first element and increment until we find the first non-null element
				m_crtEventIt = m_eventPool.begin();
				while((m_crtEventIt != m_eventPool.end()) && (*m_crtEventIt == null))
				{
					m_crtEventIt++;
				}
			}

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

				//Advance the iterator to the next event
				m_crtEventIt++;

				//keep advancing the iterator until we find the first non-null element or we reach the end
				while((m_crtEventIt != m_eventPool.end()) && (*m_crtEventIt == null))
				{
					m_crtEventIt++;
				}
			}
			
			virtual bool isDone() const
			{
				return m_crtEventIt == m_eventPool.end();
			}
			
			virtual DesEvent& currentItem()
			{
				if (m_crtEventIt == m_eventPool.end())
					throw EX("Iteration already at the end.  Cannot return item")
				
				const DesEvent& crtEvent = *(*m_crtEventIt);

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

			virtual const DesEvent& currentItem() const
			{
				if (m_crtEventIt == m_eventPool.end())
					throw EX("Iteration already at the end.  Cannot return item")

				return *(*m_crtEventIt);
			}

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

				return m_crtEventIt - m_eventPool.begin();
			}

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

		private:
			const std::vector<DesEvent*>& m_eventPool;
			mutable std::vector<DesEvent*>::const_iterator m_crtEventIt;


	};

} //end of namespace DESpot

