
/*	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 <string>
#include <vector>

#include "CommonDefinitions.h"
#include "Iterator.h"
#include "DesNotifications.h"
#include "DesTypes.h"
//#include "InstantiateTemplate.h"
//#include "Instantiation.h"

namespace DESpot
{
	class Des;
	class ProjectEventPool;
	class Instantiation;
	class DesInterface
	{
		//Types____________________________________________________
		public:
			//Des iterator
			typedef Iterator<Des&, const Des&> DesIterator; 
			typedef std::auto_ptr<DesIterator> DesIteratorPtr;
//add by bini		
			//Instantiation iterator
			typedef Iterator<Instantiation&,const Instantiation&> InstIterator;
			typedef std::auto_ptr<InstIterator> InstIteratorPtr;


		public:
			DesInterface(const std::wstring& name, ProjectEventPool& eventPool);
			DesInterface(const std::wstring& name,const DesSubsystem* subsys, ProjectEventPool& eventPool);
			virtual ~DesInterface(void);
		
		//Implementation types	
		protected:
			typedef std::map<std::wstring, Des*> DesMap;
			typedef DesMap::iterator DesMapIt;
			typedef DesMap::const_iterator DesMapCIt;
//add by bini	
			typedef std::map<std::wstring, Instantiation*> InstMap;
			typedef InstMap::iterator InstMapIt;
			typedef InstMap::const_iterator InstMapCIt;
		//Interface properties________________________________________	
		public:
			//The name of the subsystem
			std::wstring getName() const;
			void setName(const std::wstring& name);

			bool isValid() const;
			void setValid(bool setValid = true) const;
			void clearValid() const;
			Integrity getValidProp() const;


			//Read/write the interface consistency property of this interface
			bool isInterfConsist() const;
			void setInterfConsist(bool isIConsist = true) const;
			void clearInterfConsist() const;
			IConsistProp getIConsistProp() const;

		public:
			//Returns the sync product of the all the DES components. If it needs to be 
			//calculated it calculates it
			Des& getSyncDes() const;

			//Invalidates the sync product if it was computed already such that next time
			//a client asks for it a new one is produced. Used primarly when the interface is modified
			//Deep cleaning will also clean the DES components. Non-deep cleaning will only clean
			//the properties of the interface
			void clean(bool deepClean = true);

		//Access to interface's subsystem ...added by Parul
		public:
			void setSubsystem(const DesSubsystem& subsys)
			{
				m_subsys = &subsys;
			}
			const DesSubsystem& getSubsystem() const
			{
				return *m_subsys;
			}
			
		//Access to DES components _________________________________________
		public:		
			Des& getDes(const std::wstring& desName,DesLevel* out_desLevel /*= null*/);
			const Des& getDes(const std::wstring& desName,DesLevel* out_desLevel /*= null*/) const;			
			
			//Create an iterator that goes through all the internal DES of this interface
			DesIteratorPtr createDesIterator() const;
//add by bini
			DesIteratorPtr createDesIterator(DesLevel desLevel) const;
			DesIteratorPtr createDesIterator(DesLevel desLevel);
			InstIteratorPtr createInstIterator() const;
			InstIteratorPtr createInstIterator();

			int getDesCount() const;
			int getSupDesCount() const;
			int getTemplateDesCount() const;
		//Editing the DES components______________________________________
		public:
			void addDes(Des* pDes, DesLevel desLevel);
//add by bini
			void addInstantiation(Instantiation* pInstantiation);

			void changeDesName(Des& des, const std::wstring& newDesName);

			//Event sync from when a name of a DES that is part of this interface is changed using
			//the DES itself instead of the changeDesName(...) method. In this case the name  of 
			//the DES has already been changed but the interface's internal maps reference it by the old name
			//It is these internal maps that need to be updated
			void onDesNameChanged(Des* des, const std::wstring& oldName, const std::wstring& newName); 

			void deleteDes(const std::wstring& desName);
//add by bini
			void deleteInstantiation(const std::wstring& instName);

			bool findDes(const std::wstring& desName, Des** out_pDes = null, DesLevel* out_desLevel = null);
			bool findDes(const std::wstring& desName, const Des** out_pDes = null, DesLevel* out_desLevel = null) const;
//add by bini
			bool findInst(const std::wstring& instName, Instantiation** out_pInst /*= null*/) const;
			bool findInst(const std::wstring& instName, Instantiation** out_pInst /*= null*/);

		//Implemention methods
		protected:
			DesMap& getDesMap(DesLevel desLevel);
			const DesMap& getDesMap(DesLevel desLevel) const;

//add by bini
			InstMap& getInstMap();
			const InstMap& getInstMap() const;
			//Tries to find a DES with the given name either in the map of supervisor Des or in the
			//plant ones. If the DES is found, the function returns true as a result as well as the DES
			//itself, the map it was found in as well as the precise iterator pointint to it. The out parameters are
			//all optional
			bool findDes(const std::wstring& desName, Des** out_des,
							   DesMap** out_desMap = null, DesMapIt* out_desIt = null);
//add by bini
			bool findInstantiation(const std::wstring& instName, Instantiation** out_inst,
							   InstMap** out_instMap = null, InstMapIt* out_instIt = null);

		
		//serializer access
		public:
			void setLoadInProgress(bool loadInProgress = true);

		
			
		//Implementaiton methods
		private:
			void sinkDesEvents(Des* des);
			void removeDesSink(Des* des);

		private:
			//The name of the interface
			std::wstring m_name;

			//True if the subsystem is valid (all integrity checks for this subsystem are successful)
			mutable Integrity m_isValid;

			//The consistency of the interface: true if this is was verified to be an LD interface
			mutable IConsistProp m_isInterfConsist;

			//The list (actually a map) of DES that make up this interface
			DesMap m_supDesMap;
			
			DesMap m_templateDesMap;
//add by bini
			InstMap m_InstMap;

			//The synchronized product of all the DES components
			mutable Des* m_syncDes;

			//The event pool of the project this subsystem belong to
			ProjectEventPool& m_eventPool;	

			//The subsystem the interface implements. added by parul
			const DesSubsystem* m_subsys;
			
			//True when the serializer is loading the interface
			bool m_bLoadInProgress;

			//the list of sinks from all DES of the interface
			class DesNotificationSink;
			std::vector<DesNotificationSink*> m_desNotifSinks;

		//__________________________________________________________________________________________________________
	
		private: class DesNotificationSink : private DesNotifications
		{
			public:
				DesNotificationSink(DesInterface* interf, Des* source) : 
                                        m_interf(*interf), m_des(source)
				{
					m_desListenerId = m_des->subscribe(this);
				}
					
                                virtual ~DesNotificationSink()
				{
					//can't unsubscribe here because all DES could be already destroyed if the project was closed
				}
				
				Des* des() { return m_des; }

				void unsubscribe()
				{
					m_des->unsubscribe(m_desListenerId);
				}

			private:
				virtual void onNameChanged(const std::wstring& oldName, const std::wstring& newName) {m_interf.onDesNameChanged(m_des, oldName, newName);}
				virtual void onStateAdded(const DesState& /*addedState*/) { m_interf.clean();}
				virtual void onStateChanged(const DesState& /*changedState*/) { m_interf.clean();}
				virtual void onRemovingState(const DesState& /*state*/) { m_interf.clean();}
				virtual void onEventAdded(const DesEvent& /*addedEvent*/) { m_interf.clean();}
				virtual void onEventChanged(const DesEvent& /*changedEvent*/){ m_interf.clean();}
				virtual void onEventRemoved(const DesEvent::ID& /*eventId*/) { m_interf.clean();}
				virtual void onTransitionAdded(const DesTransition& /*addedTrans*/) { m_interf.clean();}
				virtual void onGlobalSelfTransitionAdded(const DesEvent& /*selfTransEvent*/) { m_interf.clean();}
				virtual void onTransitionChanged(const DesTransition& /*trans*/, const DesTransition& /*change*/) { m_interf.clean();}
				virtual void onTransitionRemoved(const DesTransition& /*removedTrans*/) { m_interf.clean();}
				virtual void onSelfTransitionRemoved(const DesEvent& /*selfTransEvent*/) { m_interf.clean();}

			private:
				DesInterface& m_interf;

				Des* m_des;
				
				unsigned int m_desListenerId;
		};

	};

}; //end of namespace DESpot
