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

#include "DespotForm.h"
#include "Des.h"
#include "TransRecorder.h"

class QMenu;
class QToolBar;
class QAction;
class QStatusBar;
class QActionGroup;

namespace DESpot
{

class MainForm;
class ProjectEditor;
class DesWorkspace;
class Des;
class DesState;
class DesEvent;
class DesTransition;
class DesEditorOutputUiPart;
class ReachabilityAlgo;
class CoreachabilityAlgo;
class NonBlockingAlgo;
class DesIntegrityAlgo;
class UpdateProgressInterface;

class DesEditor: public QMainWindow, public DespotForm
{
	Q_OBJECT

	public:
		DesEditor(MainForm* pMainForm);
		DesEditor(const std::wstring& desName, DesType desType, MainForm* pMainForm);
		DesEditor(const QString& fileName, MainForm* pMainForm);
		DesEditor(Des* pDes, ProjectEditor* projEditorOwner, MainForm* pMainForm);
		DesEditor(Des* pDes, MainForm* pMainForm);
		virtual ~DesEditor(void);

	public:
		Des* des();
		
		bool ownedByProject();
		ProjectEditor* projEditorOwner();

		TransRecorder& getTransRecorder();

		virtual QString getDocName();
		virtual QString getDocFileName(); 

		static void onAttemptSaveDes(Des* des, QWidget* callerWindow = null);

	public slots:
		//#pragma region DES slots
		//DES Slots
		void onSaveDes();
		void onSaveDesAs();
		void onRevertToFile();
		void onDesSetName();
		void onDesSetType();
		void onPrintDes();
		void onClose();
		//#pragma endregion

		//#pragma region State slots
		//State Slots
		void onAddState();
		void onChangeState();
		void onDeleteState();
		void onToggleMarkedState();
		void onMarkAllStates();
		void onUnmarkAllStates();
		void onToggleInitialState();
		
		#ifdef __ENABLE_NEXT_VERSION__		
			void onSortStatesByName();
			void onSortStatesByCreation();
			void onSortStatesByUserDefined();
		#endif

		//#pragma endregion

		//#pragma region Event slots
		//Event Slots
		void onAddEvent();
		void onChangeEvent();
		void onDeleteEvent();
		void onToggleEventCtrl();
		void onSetEventTypeDefault();
		void onSetEventTypeAnswer();
		void onSetEventTypeRequest();
		void onSetEventTypeLData();
		void onClearEventType();
		
		#ifdef __ENABLE_NEXT_VERSION__		
			void onSortEventsByName();
			void onSortEventsByCtrl();
			void onSortEventsByType();
			void onSortEventsByCreation();
			void onSortEventsByUserDefined();
		#endif

		//#pragma endregion

		//#pragma region Transitions slots
		//Transition operations
		void onAddTransition();
		void onAddTransition(const DesTransition& newTrans);
		void onAddSelfTransition();
		void onChangeTransition();
		void onDeleteTransition();		
		void onDeleteSelfTransition();		
		void onRecordTransitions();
		
		#ifdef __ENABLE_NEXT_VERSION__		
			void onFilterTransByFromState();
			void onFilterTransByToState();
			void onFilterTransByAnyState();
			void onFilterTransByEventName();
			void onFilterTransByEventType();
			void onFilterTransByEventCtrl();
			void onRemoveTransFilter();
			
			void onSortTransByFromState();
			void onSortTransByToState();
			void onSortTransByEventName();
			void onSortTransByEventType();
			void onSortTransByEventCtrl();
			void onSortTransByCreation();
			void onSortTransByUserDefined();
		#endif
		//#pragma endregion

		//#pragma region Tools Operations slots
		//Tools operations
		void onCheckDesIntegrity();
		void onRunReachableTool();
		void onRunCoreachableTool();
		void onRunNonBlockTool();
		
		#ifdef __ENABLE_NEXT_VERSION__		
			void onRunIsomorphTool();
			void onRunMultiTools();
		#endif

		//#pragma endregion

		#ifdef __ENABLE_NEXT_VERSION__				
			//User Defined Order operations
			void onMoveItemFirst();
			void onMoveItemUp();
			void onMoveItemDown();
			void onMoveItemLast();
		#endif

		//#pragma region DES slots
		//Events received from the edited DES
		void onChangedCurrentState(const DesState* pNewCurrentState, const DesState* pOldCurrentState);
		void onChangedCurrentEvent(const DesEvent* pNewCurrentEvent, const DesEvent* pOldCurrentEvent);
		void onChangedCurrentTrans(const DesTransition* pNewCurrentTrans, const DesTransition* pOldCurrentTrans);
		void onChangedCurrentSelfTrans(const DesEvent* pNewCurrentSelfTrans, const DesEvent* pOldCurrentSelfTrans);
		//#pragma endregion

	//Overridables__________________________________
	protected:
		virtual void resizeEvent(QResizeEvent* event);
		virtual void closeEvent(QCloseEvent *event);

	//Implementation Methods _______________________
	private:
		void initEditor();
	    void updateWindowTitle();
		DesEditorOutputUiPart& output();

		void showOutput(DesIntegrityAlgo& integAlgo);
		void showOutput(ReachabilityAlgo& reachAlgo);
		void showOutput(CoreachabilityAlgo& coreachAlgo);
		void showOutput(NonBlockingAlgo& nonBlockAlgo);
		
		UpdateProgressInterface* progressInterface();


	private:
		//The user interface workspace
		DesWorkspace* m_pWorkspace;

		//The DES being edited
		Des* m_pDes;

		//The state currently selected in the editor
		const DesState* m_pCrtSelState;

		//The event currently selected in the editor
		const DesEvent* m_pCrtSelEvent;

		//The transtion currently selected in the editor
		const DesTransition* m_pCrtSelTrans;

		//The self-transition currently selected in the editor (identified by the event that is self-looped)
		const DesEvent* m_pCrtSelfTrans;

		//true if the editor owns the DES and has to destroy when closed
		bool m_editorOwnsDes;

		//true if the editor is recording transitions
		TransRecorder m_transRecorder;
};

} //end of namespace DESpot
