/*	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 "ProjectEvent.h"
#include "DesSubsystem.h"

namespace DESpot
{
	class SubsystemEvent : public ProjectEvent
	{
		public:
			SubsystemEvent(void): m_owner(null) {}
			SubsystemEvent(const DesSubsystem& owner) : m_owner(&owner) {}
                        virtual ~SubsystemEvent(void) {}

		public:
			const DesSubsystem& owner() const { return *m_owner; }
			void setOwner(const DesSubsystem& owner) { m_owner = &owner; }
			bool hasOwner() const { return m_owner != null; }

			//checks if the type of project event is valid. When types of source events change
			//it is possible that if the project event pool would be re-created this would become
			//an interface event
			virtual bool isProjectEventTypeValid() const
			{
				const DesEvent* firstSrcEvent = m_srcMap.begin()->first;
				return (firstSrcEvent->getType() == eDefaultEvent);
			}

			virtual bool isValid(std::wstring* reason = null) const
			{
				bool isValid =  ProjectEvent::isValid(reason);

				if (m_owner == null)
				{
					if (reason)
					{
						*reason += L"Event doesn't have an owner\n";
					}

					isValid = false;
				}

				//Verify each source
				for (SourceMapCIt srcIt = m_srcMap.begin(); srcIt != m_srcMap.end(); srcIt++)
				{
					const Des* eventDesOwner = srcIt->second;

					//verify that the DES owner is a subsystem des
					if (eventDesOwner->getType() != eSubsystemDes && eventDesOwner->getType() != eRegularDes)
					{
						if (reason)
						{
							*reason += L"Event is used in non-subsystem DES: " + eventDesOwner->getName() + L"\n";
							isValid = false;
						}
					}
					else
					{
						//each source event has a DES as the owner. In turn each DES is owned by a subsystem
						//Check that this subsystem matches the owner of the project event. This ensures that
						//subsystem events are exclusive to each subsystem
						const DesSubsystem* eventSubsysOwner = eventDesOwner->getSubsystemOwner();
						if (eventSubsysOwner != m_owner)
						{
							if (reason)
							{
								*reason += L"Event is owned by " + m_owner->getName() + L" subsystem" +  
									       L" and is shared with another subsystem: " + eventSubsysOwner->getName() +
										  L" through DES: " + eventDesOwner->getName() + L"\n";
							}

							isValid = false;
						}
					}
				}

				return isValid;
			}

		private:
			const DesSubsystem* m_owner;
	};

} //end of namespace DESpot
