/*	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 <QTreeWidgetItem>

#include "ui_HierProjectEditor.h"
#include "ProjStructureUiPart.h"
#include "DesHierProject.h"

namespace DESpot
{
	class DesHierProject;
	class DesInterface;
	class DesSubsystem;

	class HierProjStructureUiPart: public ProjStructureUiPart
	{
		Q_OBJECT

		public:
			HierProjStructureUiPart(Ui::HierProjectEditorUI* pUiContainer, DesHierProject* pProject,
								    QAction* addHighLvlSubsysAct);
			virtual ~HierProjStructureUiPart(void);

		public:
			bool isProjectSelected();
			bool isSubsysSelected();
			bool isSupervisorSelected();
			bool isPlantSelected();
//add by bini
			bool isTemplateSelected();
			//bool isInstantiationSelected();

			bool hasCurrentProjComp();
			bool hasCurrentInterf();
			bool hasCurrentSubsys();
			virtual bool getCurrentLevel(ProjectLevel& out_level);
			virtual bool getCurrentProjComp(std::wstring& out_projCompName);
			virtual bool getCurrentDesLevel(DesLevel& out_desLevel);

			QMenu& accessHViewProjCtxtMenu();
			QMenu& accessHViewDesCtxtMenu();
			QMenu& accessLViewCtxtMenu();

			void selectDefaults();

		//Signals_______________________________________
		signals:
			void onChangedCurrentSubsys(const DesSubsystem* pNewCrtSubsys, const DesSubsystem* pOldCrtSubsys);
			void onChangedCurrentInterf(const DesInterface* pNewCrtInterf, const DesInterface* pOldCrtInterf);

			void onCurrentSubsystemDeleted();
			void onCurrentInterfaceDeleted();

		//Qt overridables
		protected:
			virtual bool eventFilter(QObject* target, QEvent* event);

		//Slots_________________________________________
		protected slots:			
			virtual void resizeProjHierStructHeaders(int width);
			virtual void resizeLevelDesHeaders(int width);
			virtual void resizeLevelViewHeaders(int width);

			virtual void onChangedCurrentFlatViewItem(QTreeWidgetItem * current, QTreeWidgetItem * previous);
			void onChangedCurrentHierViewItem(QTreeWidgetItem* current, QTreeWidgetItem* previous);
			void onChangedCurrentHierViewDesItem(QTreeWidgetItem* current, QTreeWidgetItem* previous);
			void onChangedCurrentLevelViewItem(QTreeWidgetItem* current, QTreeWidgetItem* previous);
            void onChangedCurrentHierViewInstItem(QTreeWidgetItem* current, QTreeWidgetItem* previous);


			//Called when the user uses the tab widget to change the view
			void onCurrentViewChanged(int iNewCurrentView);

			void onHViewDesItemActivated(QTreeWidgetItem* item, int column);
			void onHViewItemDeleted();
			void onHViewDesItemDeleted();
			
			void onLViewItemActivated(QTreeWidgetItem* item, int column);
			void onLViewItemDeleted();

		//Project Notifications_________________________
		private:
			virtual void onProjectNameChanged(const std::wstring& newName, const std::wstring& oldName);
			virtual void onProjectCleaned();
			
			virtual void onIConsistStatusChecked();
			virtual void onInterfIConsistStatusChanged(const DesInterface& interf);
			virtual void onSubsysIConsistStatusChanged(const DesSubsystem& subsys);

			virtual void onLwCtrlStatusChecked();
			virtual void onSubsysLwCtrlStatusChanged(const DesSubsystem& subsys);

			virtual void onLwNonBlockStatusChecked();
			virtual void onSubsysLwNonBlockStatusChanged(const DesSubsystem& subsys);

			virtual void onHighLevelSubsysAdded(const DesSubsystem& highLevelSubsys);
			virtual void onInterfaceAdded(const DesInterface& interf);
			virtual void onLowLevelSubsysAdded(const DesSubsystem& lowLevelSubsys);
			virtual void onDependencyAdded(const DesSubsystem& subsys, 
										   const DesInterface& interf, 
										   const DesSubsystem& dependent);

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

			virtual void onDeletingSubsys(const DesSubsystem& subsys);
			virtual void onDeletingInterf(const DesInterface& interf);

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

			virtual void onRemovingDes(const Des& des, DesLevel desLevel, const DesSubsystem& subsys);
			virtual void onRemovingDes(const Des& des, const DesInterface& interf);
//add by bini
			virtual void onRemovingInstantiation(const Instantiation& inst, const DesSubsystem& subsys);
			virtual void onRemovingInstantiation(const Instantiation& inst, const DesInterface& interf);
			

			virtual void onDesNameChanged(const Des& des, const std::wstring& oldName);

		private:
			virtual void initWidgets(Ui::HierProjectEditorUI* pUiContainer);

			virtual void setupConnections();

			virtual void setupProjectStructWidget();

		private:
			DesHierProject* project();

			void installEventFilters();

			void loadProjectStruct();
			void loadProjectStruct1(const DesSubsystem* p_subsys);

			QTreeWidget* getCurrentViewWidget();

		//Hieararchial View
		private:	
			void setupHierView();

			QTreeWidgetItem* createHierViewItem(const QString& text, const QString& tooltip, 
													  QTreeWidgetItem* parent = null,
													  const void* projectDes = null);

			QTreeWidgetItem* createHierViewDesItem(const QString& text, const QString& tooltip, 
													  QTreeWidgetItem* parent = null,
													  const Des* pDes = null);
//add by bini
			QTreeWidgetItem* createHierViewInstItem(const QString& text, const QString& tooltip, 
													  QTreeWidgetItem* parent = null,
													  const Instantiation* pInst = null);

			//conversion between DesSubsystem <-> QTreeWidgetItem for the Hierarchy View
			bool isSubsysHierViewItem(const QTreeWidgetItem* item);
			const DesSubsystem& getSubsystemFromHItem(QTreeWidgetItem* item);
			QTreeWidgetItem& getHViewItemFrom(const DesSubsystem& subsys);
			QTreeWidgetItem* iterateTreeWidget(const DesSubsystem& subsys,QTreeWidgetItem* item = null);

			//conversion between DesInterface <-> QTreeWidgetItem for the Hierarchy View
			bool isInterfHierViewItem(const QTreeWidgetItem* item);
			const DesInterface& getInterfaceFromHItem(const QTreeWidgetItem* item);
			QTreeWidgetItem& getHViewItemFrom(const DesInterface& interf);
			QTreeWidgetItem* iterateTreeWidget(const DesInterface& interf,QTreeWidgetItem* item = null);

			//conversion between Des <-> QTreeWidgetItem for the Hierarchy View (the Des View Widget in this view)
			bool isDesHierViewItem(const QTreeWidgetItem* item);
			Des& getDesFromHItem(const QTreeWidgetItem* item);
			QTreeWidgetItem& getHViewItemFrom(const Des& des);
			QTreeWidgetItem* iterateTreeWidget(const Des& des,QTreeWidgetItem* item = null);
			bool findHViewItemFrom(const Des& des, QTreeWidgetItem*& out_foundItem);
			bool searchDesInHViewItem(QTreeWidgetItem& desContainerItem, const Des& des, QTreeWidgetItem*& out_foundItem);
//add by bini
			bool isInstHierViewItem(const QTreeWidgetItem* item);
			Instantiation& getInstFromHItem(const QTreeWidgetItem* item);
			QTreeWidgetItem& getHViewInstItemFrom(const Instantiation& inst);
			bool findHViewInstItemFrom(const Instantiation& inst, QTreeWidgetItem*& out_foundItem);
			bool searchInstInHViewItem(QTreeWidgetItem& instContainerItem, const Instantiation& inst, 
												   QTreeWidgetItem*& out_foundItem);

			void updateDesViewer(const DesSubsystem& subsys);
			void updateDesViewer(const DesInterface& interf);
			void resetDesViewer();

			//hierachy view item properties update
			void updateHierViewItemProps(QTreeWidgetItem& hViewItem, int column, const DesSubsystem& subsys);
			void updateHViewItemIConsistProp(QTreeWidgetItem& hViewItem, const DesSubsystem& subsys);
			void updateHViewItemIConsistProp(QTreeWidgetItem& hViewItem, const DesInterface& interf);
			void updateHViewItemLwNonBlockProp(QTreeWidgetItem& hViewItem, const DesSubsystem& subsys);
			void updateHViewItemLwCtrlProp(QTreeWidgetItem& hViewItem, const DesSubsystem& subsys);
			
		//Level View
		private:
			void setupLevelView();
			
			QTreeWidgetItem* createLevelViewItem(const QString& text, const QString& tooltip, 
										  	     QTreeWidgetItem* parent = null,
												 const void* projectComp = null);

			//conversion between DesSubsystem <-> QTreeWidgetItem for the Level View
			bool isSubsysLevelViewItem(const QTreeWidgetItem* item);
			const DesSubsystem& getSubsystemFromLItem(QTreeWidgetItem* item);
			QTreeWidgetItem& getLViewItemFrom(const DesSubsystem& subsys);

			//conversion between DesInterface <-> QTreeWidgetItem for the Level View
			bool isInterfLevelViewItem(const QTreeWidgetItem* item);
			const DesInterface& getInterfaceFromLItem(const QTreeWidgetItem* item);
			QTreeWidgetItem& getLViewItemFrom(const DesInterface& interf);

			//conversion between Des <-> QTreeWidgetItem for the Level View
			bool isDesLevelViewItem(const QTreeWidgetItem* item);
			Des& getDesFromLItem(const QTreeWidgetItem* item);
			QTreeWidgetItem& getLViewItemFrom(const Des& des);
			bool searchDesInLViewItem(QTreeWidgetItem& desContainerItem, const Des& des, QTreeWidgetItem*& out_foundItem);

			const QTreeWidgetItem* getLevelItem(const QTreeWidgetItem* item);
//add by bini
			//conversation between Instantiation <-> QTreeWidgetItem for the Level View
			bool isInstLevelViewItem(const QTreeWidgetItem* item);
			Instantiation& getInstFromLItem(const QTreeWidgetItem* item);
			QTreeWidgetItem& getLViewInstItemFrom(const Instantiation& inst);
			bool searchInstInLViewItem(QTreeWidgetItem& instContainerItem, const Instantiation& inst, QTreeWidgetItem*& out_foundItem);

		//Internal data
		private:
			const DesSubsystem* m_pCrtSubsys;
			const DesInterface* m_pCrtInterf;

			QAction* m_addHighLvlSubsysAct;

			QMenu m_hViewProjCtxtMenu;
			QMenu m_hViewDesCtxtMenu;
			QMenu m_lViewCtxtMenu;

		//Widgets
		private:
			QTabWidget* m_projStructTabWidget;
			int m_crtView;

			//Hierarchy View
			QSplitter* m_hViewSplitterWidg;
			DespotTreeWidget* m_hViewProjStructWidg;
			QTreeWidgetItem*  m_hViewRootItem;
			QTreeWidgetItem*  m_hViewRootSubsysItem;
			QTreeWidgetItem* m_hViewLowlevelSubsysItem;
			
			DespotTreeWidget* m_desViewWidg;
			QTreeWidgetItem*  m_desViewRootItem;
			QTreeWidgetItem*  m_supDesRootItem;
			QTreeWidgetItem*  m_plantDesRootItem;
//add by bini
			QTreeWidgetItem* m_templateDesRootItem;

			//Level View
			DespotTreeWidget* m_lViewProjStructWidg;
			QTreeWidgetItem*  m_lViewRootItem;
			QTreeWidgetItem*  m_lViewRootSubsysItem;
			QTreeWidgetItem*  m_highLevelItem;
			QTreeWidgetItem*  m_interfLevelItem;
			QTreeWidgetItem*  m_lowLevelItem;

			//Flat View
			//The widget for flat view is inherited from ProjStructureUiPart. However the setup
			//is different since it displays the flat view of a HISC project
		
		//Constants
		private:
			static const int cHierViewIndex;
			static const int cLevelViewIndex;
			static const int cFlatViewIndex; 

			static const int cHierProjStructColCount;
			static const int cContainerNameColIndex;
			static const int cIcColIndex;
			static const int cNbColIndex;
			static const int cCtrlColIndex;

			static const int cLevelDesColCount;
			static const int cDesNameColIndex;
			static const int cDesStatusColIndex;

			static const int cLevelViewProjStructColCount;
			static const int cSupChildIdx;
			static const int cPlantChildIdx;
//add by bini
			static const int cTemplateChildIdx;

			static const QString cPropTrueSymbol;
			static const QString cPropFalseSymbol;
			static const QString cPropBlankSymbol; 
			
			//parul
			protected:
			typedef std::map<const QTreeWidgetItem*, int> HViewLevelIndexMap;
			typedef HViewLevelIndexMap::iterator HViewLevelIndexIt;

			protected:
			//The subsystem level in the dependency tree
			int m_level;

			//The map of dependecies to other subsystems
			HViewLevelIndexMap m_levelIndexMap;
	};

} //end of namespace DESpot
