/*	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 <memory>
#include "DesEvent.h"
#include "Des.h"

namespace DESpot
{
	class SourceIterator;

	class ProjectEvent : public DesEvent
	{
		public:
			struct Source
			{
				const DesEvent* event;
				Des* des; //the owner of the event
			};

			typedef std::auto_ptr<SourceIterator> SourceIteratorPtr;

		public:
			ProjectEvent(void);
                        virtual ~ProjectEvent(void);
		
		public:
			void addSourceEvent(const DesEvent* desEvent, Des* eventOwner);
			
			void removeSourceEvent(const DesEvent* desEvent);

			bool findSourceEvent(const DesEvent* desEvent);

			void changeEvent(const DesEvent& desEvent);
			
			void changeEventName(const std::wstring& newName);

			SourceIteratorPtr createSourceIterator() const;

			unsigned int  sourceCount();

			//checks if all the source events are consistent (have the same properties)
			virtual bool isValid(std::wstring* reason = null) const;

			bool isAliasValid();
			void updateAliasFromSources();

			bool isCtrlValid();
			void updateCtrlFromSources();

			//checks if the type of project event is valid. If it is a subsystem event the owner
			//of the first source must be a subsystem. If it is an interface than the type should be
			//interface
			virtual bool isProjectEventTypeValid() const = 0;

			bool isTypeConsistent(EventType srcType) const;

			
		
		protected:
			typedef std::map<const DesEvent*, Des*> SourceMap;
			typedef SourceMap::iterator SourceMapIt;
			typedef SourceMap::const_iterator SourceMapCIt;

		protected:
			SourceMap m_srcMap;
	};

	//______________________________________________________________________________________________

	class SourceIterator: public Iterator<ProjectEvent::Source, const ProjectEvent::Source>
	{
		public:
			SourceIterator(const std::map<const DesEvent*, Des*>& srcMap):
						m_srcMap(srcMap)
			{
			}
		
			virtual ~SourceIterator(void)
			{
			}
	
		public:
			virtual void first() const
			{
				m_crtSrcIt = m_srcMap.begin();
			}
			
			virtual void next() const
			{
				m_crtSrcIt++;
			}
			
			virtual bool isDone() const
			{
				return (m_crtSrcIt == m_srcMap.end());
			}
			
			virtual ProjectEvent::Source currentItem()
			{
				if (m_crtSrcIt == m_srcMap.end())
					throw EX("Iterator is already done. Call isDone() before.")

				ProjectEvent::Source src;
				src.event = m_crtSrcIt->first;
				src.des = m_crtSrcIt->second;

				return src;
			}
			
			virtual const ProjectEvent::Source currentItem() const
			{
				if (m_crtSrcIt == m_srcMap.end())
					throw EX("Iterator is already done. Call isDone() before.")

				ProjectEvent::Source src;
				src.event = m_crtSrcIt->first;
				src.des = m_crtSrcIt->second;

				return src;
			}


		private:
			//no copying allowed
			SourceIterator(const SourceIterator& other) : m_srcMap(other.m_srcMap) {}
			SourceIterator& operator=(const SourceIterator& /*other*/) {return *this;}

		private:
			typedef std::map<const DesEvent*, Des*> SrcMap;
			typedef SrcMap::const_iterator SrcMapIt;

		private:
			const SrcMap m_srcMap;
			mutable SrcMapIt m_crtSrcIt;	
	};

} //end of namespace DESpot
