/*************************************************************************
 * 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
   SimConfig.h - Simulation configuration 
 FUNCTION
   Simulation configuration definition
 NOTES
   
 MODIFIED
   xma		04/01/08 - Integrate to DESpot
   xma	    09/01/07 - CREATION. 
*/

#ifndef SIMCONFIG_H 
#define SIMCONFIG_H

#pragma once

//#include "OutputUiPart.cpp"
#include <QtCore>
#include <QMainWindow>
#include <QCloseEvent>

#include "DespotForm.h"
#include "ProjectEvent.h"
#include "SimCompState.h"


class QTabWidget;

namespace DESpot
{ 
class MainForm;
class EventPoolForm;
class SimWorkspace;
class DesProject;
class Des;
class OutputUiPart;
class UpdateProgressInterface;
class SimAlg;
class DesHierProject;
class DesFlatProject;
class SimConfigWizard;
class ProjectEditor;

class SimStopCondition
{
public:
	enum StopOptions {UNLIMITED, STEP, REACH_INIT, REACH_MARKED, EVENTSEQ};

	StopOptions  option;
	unsigned long step;

	SimStopCondition(StopOptions op=UNLIMITED);

	void setOption(StopOptions op)
		{option = op;}
	void setStep(unsigned long step)
		{this->step = step;}
};
	

class SimConfig: public QMainWindow, public DespotForm
{
Q_OBJECT

public:

	// The project event set, this event set is ordered. 
	// The client may choose to ignore the order
	typedef QMultiMap<unsigned long, const ProjectEvent*> ProjectEventSet;

	enum SimMode {HIER, FLAT, HIERASFLAT};
	enum EventSetMode {SEQ, SET};
	enum { MagicNumber = 0xF26C0056 };

	//SimConfig(MainForm* pMainForm, FormType formType);
	SimConfig(DesProject* project, MainForm* pMainForm, ProjectEditor* projEditorOwner, FormType formType);
	//SimConfig(DesProject* project, FormType formType);
	~SimConfig(void);
	void setModified(bool modified)
	 	{this->modified = modified;}
	bool isModified()
		{return modified;}

	void initSimConfig();

	DesProject* project();
    ProjectType getProjectType() const;
	SimMode getSimMode()
		{return simMode;}
	EventSetMode getEventSetMode()
		{return eventSetMode;}
	void setEventSetMode(SimConfig::EventSetMode mode)
	{eventSetMode = mode;}
	//note: test run set condition in construction SimConfig::SimConfig
	SimStopCondition getStopCondition()  
		{return stopCondition;}
	SimCompState::StateTuple getInitStateTuple()
		{return initStateTuple;}
	ProjectEventSet getEventSet()
		{return eventSet;}
	void setEventSet(ProjectEventSet eventSet)
		{this->eventSet=eventSet;}
	ProjectEventSet getCompleteProjEventSet();

	QString& getTraceFileName()
	{return traceFileName;}
//	void setTraceFileName(QString& fname)
//	{traceFileName = fname;}
	bool isProjInerfaceConsistent();
	bool isProjectBilevel();


	//Called by wizard to set configuration
	void setConfig(	SimMode simMode,
				EventSetMode eventSetMode,
				SimStopCondition stopCondition,
				SimCompState::StateTuple initStateTuple,	//Init state
				ProjectEventSet eventSet);						//Event set


	void closeEvent(QCloseEvent *event);

public slots:
	bool okToContinue();
	void onOpenFile();
	bool onSaveFile();
	bool onSaveAsFile();

	/*
	void onSaveConfig();
	void onSaveConfigAs();
	void onPrintConfig();
	void onCloseConfig();
	void onStepForward();
	void onStepBackward();
	*/

protected:
	virtual bool eventFilter(QObject* target, QEvent* event);						
	void updateWindowTitle();
	//void saveConfigDes();
	//OutputUiPart& output();
	//UpdateProgressInterface* progressInterface();

	//added by zain to load counter example in simulator
public:
	void CounterExampleConfig(ProjectEventSet& CEEventSet);
	void ErrorStateConfig(SimCompState::StateTuple& in_tuple);

private:

	void createDefaultConfig();
	bool loadFile(const QString &fileName);
	bool readFile(const QString &fileName);
	bool saveFile(const QString &fileName);
	bool writeFile(const QString &fileName);
	void setTraceFileName();
	void initSimAlg();

	void setCurrentFile(const QString &fileName);
	QMap<QString,ProjectEvent*> createEvLookupTab();
	QMap<QString,Des*> createDesLookupTab();

	QString eventFile;
	bool modified;

	DesProject* desProject;
	DesFlatProject *flatProject;
	DesHierProject *hierProject;
	SimWorkspace* workSpace;
	EventPoolForm* eventPoolForm;
	SimConfigWizard* wizard;

	//The current component in the project
	//Des* currentDes;

	//SimAlg* simAlg;
	// The parameters to pass to SimAlg
	SimMode simMode;
	EventSetMode eventSetMode;
	SimStopCondition stopCondition;
	SimCompState::StateTuple initStateTuple;	//Init state
	ProjectEventSet eventSet;						//Event set

	QString traceFileName;

};

#define DEFAULT_FLUSH_TRACE_STEPS 20
#define DEFAULT_TRC_DES_PREFIX_STEPS 1

} //end of namespace DESpot
#endif
