/*************************************************************************
 * This file is part of DES simulation project    
 *
 * Project created in conformity with the requirements for the Degree of
 * Master of Engineering in Software Engineering, Computing and Software
 * Department, McMaster University 2004 - 2008
 *
 * Author:	Xiao Ma
 * Supervisor: Dr. Ryan Leduc
*************************************************************************/

/* 
 NAME
   SimWorkspace.cpp - Simulation workspace 
 FUNCTION
   Simulator user interface management
 NOTES
   
 MODIFIED
   xma	    05/01/08 - CREATION. 
*/

#ifndef SimWorkspace_H 
#define SimWorkspace_H 

#pragma once

#include <QtGui>

#include "Workspace.h"
#include "OutputWidget.h"
#include "ui_SimHierConfig.h"
#include "DesProject.h"
#include "SimStateModel.h"
#include "SimEventModel.h"
#include "Des.h"
#include "SimGedViewer.h"

namespace DESpot
{
//class Des;
class DesProject;
class DesHierProject;
class DesFlatProject;
class EventPoolForm;
class SimConfig;
class SimStopCondition;
class SimConfigSumUiPart;
class OutputUiPart;
class ProgressWidget;
class ProjEventSetWidget;
class SimStateDelegate;
class SimAlg;
class SimCompState;

class SimWorkspace: public Workspace, private Ui::SimHierConfigUI
{
Q_OBJECT 

public:
	typedef QMap<const Des*, SimGedViewer*> SimGedViewerMap;

	SimWorkspace(SimConfig* simConfig, DesProject* project);
	~SimWorkspace(void);

	bool eventFilter(QObject* target, QEvent* event);
	void writeTrace(const QString &str);
	SimConfig* config(){return simConfig;}
	QMultiMap<unsigned long, const ProjectEvent*> getHistEventSeq();
	void updateRunStatus();
	void updateHistStatus(int row);
	bool simRunning();

public slots:
	void onNewSimulation();
	void onStartWizard();
	void onPrintSimulation();
	void onCloseSimulation();
	void onStartSimulation();
	void onSimAlgStatusChanged();
	void enableTrace(bool enable);
	void enableHist(bool enable);
	bool onFlushTraceFile(bool force);
	void configChanged();
	void cleanCurrentSim();
	void onStopSimulation();
	void onExitSimulation();

private slots:
	void stepsChanged(const QString &str);
	void delayChanged(const QString &str);
	void trcStepChanged(const QString &str);
	void trcFlushChanged(const QString &str);
	void stopStepChanged(const QString &str);
	void trcViewToolChanged(const QString &str);
	void viewTrace();
	void viewGed();

	void onRunSimulation();
	void runFlatMode();
	void runHISCMode();

	void histDisabled();
	void histEnabled();


	void onStepForward();

	void oneStepForwardFlat(); //slow mode
	void oneStepForwardHISC(); //slow mode

	void onStepBackward();
	void onStepBackward(int stepsToGo);
	void onHistoryView();
	void onRunView();
	void onStopConditionChanged(int type);
	void onTrcViewToolChanged(int type);
	void histEventViewClicked(const QModelIndex & index);
	void eligEventViewDoubleClicked(const QModelIndex & index);
	void eligEventViewClicked(const QModelIndex & index);
	void ineligEventViewClicked(const QModelIndex & index);
	void currentStateViewDoubleClicked(const QModelIndex & index);
	void setSlowMode(bool fast);
	void gotoSpecifiedStep();

	void onViewerVisibilityChange(bool visible);

private:

	//Main Windows to place menus etc.
	SimConfig* simMainWindow();
	void createActions();
	void createMenus();
	void createToolBar();
	void createStatusBar();
	void createEventSetTab();
	void createRuntimeTab();
	void createLayout();
	void createConnections();
	void createEventFilters();
	void updateHistView();
	void resetSimAlg();
	void reportStateTuple();
	void setStopCondition(SimStopCondition condition);


	void setSimTitle();
	void createInitStateTab();
	void positionSplitters();
	//clean the current simulation task
	ProjectEvent* getChoosenEvent();
	void updateViewers();
	void cleanOldTrace();
	SimGedViewer* getSimViewer(Des* pDes);
	void deleteSimViewers();
	void resetSimViewers();
	void resizeColumnsToContents(QTreeView* view);
	void markBlockingDes(Node* parent);
	void updateGedViewers(SimCompState* pCurState, bool isRunningMode = true);

	QAction* newAct;
	QAction* openAct;
	QAction* saveAct;
	QAction* saveAsAct;
	QAction* wizardAct;
	QAction* printAct;
	QAction* closeAct;
	QAction* stepForwardAct;
	QAction* stepBackwardAct;
	QAction* toggleTraceAct;
	QAction* toggleHistAct;
	QAction* toggleFastAct;
	QAction* startSimulateAct;
	QAction* stopSimulateAct;
	QAction* histViewAct;
	QAction* runViewAct;
	QAction* traceViewAct;
	QAction* gedViewAct;

	QAction* gotoAct;
	QAction* aboutAct;
	QAction* helpAct;

	QMenu* fileMenu;
	QMenu* runMenu;
	QMenu* viewMenu;
	QMenu* helpMenu;

	QComboBox*  stepsCombo;
	QToolBar* toolsToolBar;

	//Status indicator in toolbar
	QLabel* prevEventDisplay;
	QLabel* nextEventDisplay;
	QComboBox*  gotoCombo;


	//Stop condition editor
	QButtonGroup *stopConditionGroup;
	QRadioButton* unlimitRadioButton;
	QRadioButton* stepRadioButton;
	QRadioButton* markedStateRadioButton;
	QRadioButton* initStateRadioButton;
	QComboBox* stepCombo;

	//trace viewer external editor
	QButtonGroup *trcvtGroup;
	QRadioButton *viRadioButton;
	QRadioButton *npRadioButton;
	QRadioButton *udRadioButton;
	QComboBox *udCombo;

	DesProject* desProject;
	SimEventModel* selectedEventModel;
	SimEventModel* eligEventModel;
	SimEventModel* ineligEventModel;
	SimEventModel* histEventModel;
	SimConfig* simConfig;
	SimAlg* simAlg;

	SimStateModel* stateModel;  //init state model
	SimStateModel* currentStateModel;
	SimStateModel* nextStateModel;
	SimStateDelegate* currntStateDelegate;

	unsigned long lastFlushStep; //keep track of where the trace was last written out
	int stepsToFlush;

	//slow mode
	bool canContinue;
	bool slowMode;
	int  slowModeDelay;         // Delay in slow mode, in millisecond
	QComboBox* delayCombo;
	QLabel* stepDisplay_3;

	//run time 
	QLabel* simStatusDisplay;
	QComboBox* trcStepCombo;
	QComboBox* trcFlushCombo;

	QString trcViewTool;

	int eligViewCurrentRow;
	int ineligViewCurrentRow;

	SimGedViewerMap m_simGedViewers;
};

} //end of namespace DESpot

#endif
