/*	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
*/
//modified
#pragma once

//This warning must be disabled in the Visual C++ project. Using #pragma warning is not supported by GCC so
//the line below is used only as a comment that this warning was verified.
//#pragma warning(disable:4250)

#include <map>
#include <memory>
#include "DesProject.h"
#include "Iterator.h"

#include "BddHiscMain.h"

#include "DistCommon.h"
//add by bini
//#include "InstantiateTemplate.h"
//#include "Instantiation.h"

namespace DESpot
{
	class Instantiation;
	class DesInterface;
	class IConsistAlgo;
	class LwNonBlockingAlgo;
	class LwCtrlAlgo;
	class HighSubsysNonBlockAlgo;
	class LowSubsysNonBlockAlgo;
	class IConsistAnsAcceptAlgo;
	class LowSubsysIConsistAlgo;
	class LdInterfaceCheckAlgo;
	class HighSubsysCtrlAlgo;
	class LowSubsysCtrlAlgo;

	class HierSerializerAccess: virtual public ProjSerializerAccess
	{
		public:
			virtual void setIConsistProp(int iConsProp) = 0; 			
			virtual void setIConsistStamp(const std::wstring& iConsStamp) = 0; 
			
			virtual void setLwNonBlockProp(int lwNonBlockProp) = 0; 
			virtual void setLwNonBlockStamp(const std::wstring& lwNonBlockStamp) = 0; 
			
			virtual void setLwCtrlProp(int lwCtrlProp) = 0; 
			virtual void setLwCtrlStamp(const std::wstring& lwCtrlStamp) = 0; 

			virtual void addHighLevelSubsys(DesSubsystem* subsyss) = 0;
			virtual void addInterface(DesInterface* interf) = 0;
			virtual void addLowLevelSubsys(DesSubsystem* subsys) = 0;

			virtual DesSubsystem* getSubsystem(const std::wstring& name) = 0;
			virtual DesInterface* getInterface(const std::wstring& name) = 0;
	};

	class DesHierProject :	public DesProject, protected HierSerializerAccess
	{
		//Types
		public:
			typedef Iterator<DesInterface&, const DesInterface&> InterfIterator; 
			typedef std::auto_ptr<const InterfIterator> InterfIteratorPtr;

			typedef Iterator<DesSubsystem&, const DesSubsystem&> SubsysIterator; 
			typedef std::auto_ptr<const SubsysIterator> SubsysIteratorPtr;

		public:
			DesHierProject(const std::wstring& name);
			virtual ~DesHierProject(void);

		//HISC project specific properties
		public:			
			//The degree of the project (number of low-level subsystems)
			//Cannot be set as it depends on the the actual subsystem structure
			int getDegree() const;
			
			//Check if Hier project is bilevel or multilevel____________added by parul 
			bool isBilevel() const;

			//Interface consistent property
			bool	     isInterfConsist() const;
			IConsistProp getIConsistProp() const;
			std::wstring getIConsistStamp() const;			
			bool		 checkIConsistProp(IConsistAlgo& iConsAlgo);
			bool		 checkIConsistProp(IConsistAlgo& iConsAlgo,std::map<std::wstring,bool> &subsysIConsMap,DesHierProject* mainProject);
			bool		 checkIConsistProp(IConsistAlgo& iConsAlgo,bool multi);
			bool         checkInterfIConsistProp(LdInterfaceCheckAlgo& interfIConsistAlgo);
			bool		 checkSubsysIConsistProp(IConsistAnsAcceptAlgo& ansAcceptAlgo);
			bool		 checkSubsysIConsistProp(LowSubsysIConsistAlgo& lowSubsysIConsAlgo);			
			void		 setIConsistPropMainProj(bool isICons);
			void		 setSubsysIConsistPropMainProj(const DesSubsystem& subsysMainProj,bool isSubIConst);

#ifdef __ENABLE_BDD__
			void              procBddIConsistProp(BDDHISC::Hisc_ChkInfo& checkInfo); 
			void              procBddHighIConsistProp(BDDHISC::Hisc_ChkInfo& checkInfo); 
			void              procBddLowIConsistProp(BDDHISC::Hisc_ChkInfo& checkInfo,  const DesSubsystem& lowSubsysToCheck); 
			void              procBddInterfProp(BDDHISC::Hisc_ChkInfo& checkInfo, const DesInterface&  interfToCheck); 
#endif

			//Level-wise non-blocking
			bool		   isLwNonBlocking() const;
			LwNonBlockProp getLwNonBlockProp() const;
			std::wstring   getLwNonBlockStamp() const;				
			bool		   checkLwNonBlockProp(LwNonBlockingAlgo& lwNonBlockAlgo);
			bool		   checkLwNonBlockProp(LwNonBlockingAlgo& lwNonBlockAlgo,std::map<std::wstring, bool> &subsysNonBlockMap);
			bool		   checkLwNonBlockProp(LwNonBlockingAlgo& lwNonBlockAlgo,bool multi);
			bool		   checkSubsysNonBlockProp(HighSubsysNonBlockAlgo& hSubsysNonBlockAlgo);
			bool		   checkSubsysNonBlockProp(LowSubsysNonBlockAlgo& lowSubsysNonBlockAlgo);
			void		   setLwNonBlockPropMainProj(bool isNonBlock);
			void		   setSubsysNonBlockPropMainProj(const DesSubsystem& subsys, bool isNonBlock);

#ifdef __ENABLE_BDD__
			void               procBddLwNonBlockProp(BDDHISC::Hisc_ChkInfo& checkInfo); 
			void               procBddHighNonBlockProp(BDDHISC::Hisc_ChkInfo& checkInfo); 
			void
			procBddLowNonBlockProp(BDDHISC::Hisc_ChkInfo& checkInfo,  const DesSubsystem& lowSubsysToCheck); 
#endif

			//Level-wise controllable
			bool		 isLwControllable() const;
			LwCtrlProp   getLwCtrlProp() const;
			std::wstring getLwCtrlStamp() const;
			bool         checkLwCtrlProp(LwCtrlAlgo& lwCtrlAlgo); 
			bool         checkLwCtrlProp(LwCtrlAlgo& lwCtrlAlgo,std::map<std::wstring, bool> &subsysCtrlMap);
			bool         checkLwCtrlProp(LwCtrlAlgo& lwCtrlAlgo,bool multi); 
			bool         checkSubsysLwCtrlProp(HighSubsysCtrlAlgo& hSubsysLwCtrlAlgo); 
			bool         checkSubsysLwCtrlProp(LowSubsysCtrlAlgo& lowSubsysLwCtrlAlgo); 
			void		 setLwCtrlPropMainProj(bool isCtrl);
			void		 setSubsysCtrlPropMainProj(const DesSubsystem& subsysChecked, bool isSubContrl);

#ifdef __ENABLE_BDD__
			void               procBddLwCtrlProp(BDDHISC::Hisc_ChkInfo& checkInfo); 
			void               procBddHighCtrlProp(BDDHISC::Hisc_ChkInfo& checkInfo); 
			void
			procBddLowCtrlProp(BDDHISC::Hisc_ChkInfo& checkInfo,  const DesSubsystem& lowSubsysToCheck); 
#endif

			//Resets all properties and all incremental data calculated for them
			//so that they can be rechecked from scratch
			//Deep cleaning will also clean the DES components. Non-deep cleaning will only clean
			//the properties of the project
			virtual void clean(bool deepClean = true);

		//Subsystem operations
		public:
			const DesSubsystem& addHighLevelSubsys(const std::wstring& name);
			const DesInterface& addInterface(const std::wstring& name);
			const DesSubsystem& addLowLevelSubsys(const std::wstring& name, const std::wstring& interfName);
			const DesInterface& addInterface(const std::wstring& name,const std::wstring& subsysName);//added Parul

			void renameSubsystem(const std::wstring& name, const std::wstring& newName);
			void renameSubsystem(const DesSubsystem& subsys, const std::wstring& newName);
			void renameInterface(const std::wstring& name, const std::wstring& newName);
			void renameInterface(const DesInterface& interf, const std::wstring& newName);

			void deleteSubsystem(const std::wstring& name);
			void deleteInterface(const std::wstring& name);

			int getInterfaceCount() const;
			const DesInterface& getInterface(const std::wstring& name) const;
			InterfIteratorPtr createInterfIterator() const;

			int getSubsystemCount() const;
			const DesSubsystem& getSubsystem(const std::wstring& name) const;
			//virtual DesSubsystem* getSubsystem(const std::wstring& name);
			SubsysIteratorPtr createSubsysIterator() const;

		//Des operations
		public:
			void addDes(Des* pDes, const std::wstring& container, DesLevel desLevel = eSupervisorDes);
			void addDes(Des* pDes, const DesSubsystem& subsys, DesLevel desLevel);
			void addDes(Des* pDes, const DesInterface& interf, DesLevel desLevel);
			
//add by bini
			bool addInstantiation(Instantiation* pInstantiation,Des* template_crt);

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

			//removes a DES from the project and destroys it
			virtual void deleteDes(const std::wstring& desName);
			void deleteDes(const std::wstring& desName, const DesSubsystem& parentSubsys);
			void deleteDes(const std::wstring& desName, const DesInterface& parentInterf);
//add by bini
			virtual void deleteInstantiation(const std::wstring& instName){};
			void deleteInstantiation(const std::wstring& desName, DesSubsystem& parentSubsys);
			void deleteInstantiation(const std::wstring& desName, DesInterface& parentInterf);

			const DesInterface& getParentInterface(const Des& des);
			const DesSubsystem& getParentSubsystem(const Des& des);

			//Create an iterator that goes through all the DES in the project
			virtual DesIteratorPtr createDesIterator() const;
			virtual DesIteratorPtr createDesIterator();

			//Create an iterator that goes through either the plant or the supervisor Des
			virtual DesIteratorPtr createDesIterator(DesLevel desLevel) const;
			virtual DesIteratorPtr createDesIterator(DesLevel desLevel);
//add by bini
			void instantiatetemplate(const std::wstring& templateName,Instantiation* inst,DesSubsystem* sub);
			void instantiatetemplate(const std::wstring& templateName,Instantiation* inst,DesInterface* interf);

		//Internal Types
		private:
			typedef std::map<std::wstring, DesInterface*> InterfaceMap;
			typedef InterfaceMap::iterator InterfaceMapIt;
			typedef InterfaceMap::const_iterator InterfaceMapCIt;

			typedef std::map<std::wstring, DesSubsystem*> SubsystemMap;
			typedef SubsystemMap::iterator SubsystemMapIt;
			typedef SubsystemMap::const_iterator SubsystemMapCIt;

		//Serializer access
		private:
			virtual void setIConsistProp(int iConsProp); 			
			virtual void setIConsistStamp(const std::wstring& iConsStamp); 
			virtual void setLwNonBlockProp(int lwNonBlockProp); 
			virtual void setLwNonBlockStamp(const std::wstring& lwNonBlockStamp); 
			virtual void setLwCtrlProp(int lwCtrlProp); 
			virtual void setLwCtrlStamp(const std::wstring& lwCtrlStamp); 		
			virtual void addHighLevelSubsys(DesSubsystem* subsys);
			virtual void addInterface(DesInterface* interf);
			//virtual void addInterface(const DesInterface* interf);
			virtual void addLowLevelSubsys(DesSubsystem* lSubsys);		
			virtual DesSubsystem* getSubsystem(const std::wstring& name);
			virtual DesInterface* getInterface(const std::wstring& name);

		//Implementation methods
		public:
			void onIConsistStatusChanged();
			void onIConsistStatusChecked();
			void onInterfIConsistStatusChanged(const DesInterface& interf);
			void onSubsysIConsistStatusChanged(const DesSubsystem& subsys);

			void onLwCtrlStatusChanged();
			void onLwCtrlStatusChecked();
			void onSubsysLwCtrlStatusChanged(const DesSubsystem& subsys);
			
			void onLwNonBlockStatusChanged();
			void onLwNonBlockStatusChecked();
			void onSubsysLwNonBlockStatusChanged(const DesSubsystem& subsys);
			
			void onHighLevelSubsysAdded(const DesSubsystem& highLevelSubsys);
			void onInterfaceAdded(const DesInterface& interf);
			void onLowLevelSubsysAdded(const DesSubsystem& lowLevelSubsys);
			void onDependencyAdded(const DesSubsystem& subsys, const DesInterface& interf, const DesSubsystem& dependent);

			void onSubsysRenamed(const DesSubsystem& subsys);
			void onInterfRenamed(const DesInterface& interf);

			void onDeletingSubsys(const DesSubsystem& subsys);
			void onSubsysDeleted(const std::wstring& subsysName);
			
			void onDeletingInterf(const DesInterface& interfName);
			void onInterfDeleted(const std::wstring& interfName);

			void onDesAdded(const Des& des, DesLevel desLevel, const DesSubsystem& subsys);
			void onDesAdded(const Des& des,  DesLevel desLevel,const DesInterface& interf);
//add by bini	
			void onInstAdded(Instantiation& addedInst, Des& template_crt);

			void onRemovingDes(const Des& des, DesLevel desLevel, const DesSubsystem& subsys);
			void onRemovingDes(const Des& des, const DesInterface& interf);

			void onDesRemoved(const std::wstring& desName, DesLevel desLevel, const DesSubsystem& subsys);
			void onDesRemoved(const std::wstring& desName, const DesInterface& interf);

//add by bini
			void onRemovingInstantiation(const Instantiation& inst, const DesSubsystem& subsys);
			void onRemovingInstantiation(const Instantiation& inst, const DesInterface& interf);
			void onInstantiationRemoved(const std::wstring& instName, const DesSubsystem& subsys);
			void onInstantiationRemoved(const std::wstring& instName, const DesInterface& interf);
			
		//Distributed computation methods
		public:
			void setFlags(resultStruct rs);

		//Data
		private:
			//The degree of the HISC project (number of low-level subsystems)
			int m_degree;

			//Interface consistency property
			IConsistProp m_iConsistProp;

			//The date-time stamp when the interface consistency property was checked
			std::wstring m_iConsistStamp;

			//Level-wise non-blocking property
			LwNonBlockProp m_lwNonBlockProp;

			//The date-time stamp when the level-wise non-blocking property was checked
			std::wstring m_lwNonBlockStamp;

			//Level-wise controllable property
			LwCtrlProp m_lwCtrlProp;

			//the date-time stamp when the level-wise controllability property was checked
			std::wstring m_lwCtrlStamp;
			
			//The map of interfaces part of this project
			InterfaceMap m_interfMap;			

			//The map of subsystems; includes the root subsystem for completness
			SubsystemMap m_subsysMap;
		
	};
}; //end of namespace DESpot
