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

#ifndef SimCompState_H 
#define SimCompState_H

#include <utility>
#include <map>
#include <vector>
#include <string>
#include <set>

#include "Des.h"
#include "DesProject.h"
#include "DesEvent.h"
#include "DesHierProject.h"
#include "DesState.h"
#include "DesTransition.h"
#include "InterfaceEvent.h"
#include "SubsystemEvent.h"
#include "DesInterface.h"


/* Composite state definition when doing sync, meet, simulation which
 * involve various number of Des. Considerations:
 * 1. The number of Des invovled varies, so a composite state will be a
 *    dynamic array with each element stands for (Des,state)
 * 2. Need very easy access to Des and state, preferable direct access like
 *    DesTab[Des]->state->tansition
 * 3. We need to keep track of states and transition both forward and
 *    backward. So the state will need to be doubly linked and each link
 *    need to be associated with an event
 */
namespace DESpot
{

class SimAlg;

class SimCompState
{
public:
	typedef std::map<Des*,DesState*> StateTuple; 

	SimCompState(StateTuple& gstate, SimAlg* simAlg);
	~SimCompState();

	std::set<ProjectEvent*>& getEligEvents();

	ProjectEvent* getChoosenEvent()
		{return eventChoosen;}
	void setChoosenEvent(ProjectEvent* ev)
		{eventChoosen=ev;}

	StateTuple* getCurrentState()
		{return &currentState;};
	StateTuple getNextStateTuple(ProjectEvent* ev);
	SimCompState* getNextState()
		{return nextCompState;}
	SimCompState* getPrevState()
		{return prevCompState;}
	void setNextState(SimCompState* st)
		{nextCompState=st;}
	void setPrevState(SimCompState* st)
		{prevCompState=st;}
	void setRevEvent(ProjectEvent* ev)
		{reverseEvent=ev;}
	bool isInit()
		{return initState;}
	bool isMarked()
		{return markedState;}
	ProjectEvent* getReverseEvent()
	{return reverseEvent;}
	ProjectEvent* getNextEvent()
	{return eventChoosen;}

	void printState(StateTuple* sta);
	void printShortState(QString title);
	void printLongState(QString title);
	void printEligEvents();
	void printLevelSet(QString title, std::set<const DesSubsystem*>& levelSet);
	void computeEligEventFlat(bool computeNextState);       /* get eligible events*/
	void computeEligEventHISC(bool computeAllEligEvent);
	void computeEligEventHISCAll();
	void computeEligEventHISCLevelOptim();
	void computeEligEventSeqHISC();
	void computeNextState(const ProjectEvent* projEvent);
	void computeNextStateHISC(const ProjectEvent* projEvent); //Add HISC optim
	bool isNextStateComputed(const ProjectEvent* projEvent);
	std::map<ProjectEvent*,StateTuple>& getEligNextState()
		{return eligNextState;}

	//In HISC mode, we stop looking up events when we find eligible events 
	//in one level, in this case, allEligEventFound is set to false
	bool areAllEligEventsFound()
		{return allEligEventFound;}


	static StateTuple getInitGlobalState(const DesProject* proj);

private:

	bool eventEligChanged(ProjectEvent* ev, std::set<const DesSubsystem*> &recompLevelSet);

	void setStateType();
	void dbg(QString str);
	void writeTrace(QString str);
	
	StateTuple		currentState;
	bool			markedState;						// marked or not
	bool            initState;							// initial or not
	std::map<ProjectEvent*,StateTuple> eligNextState;	//and their next states
	std::set<ProjectEvent*>	eligEventSet;				//and their next states

	ProjectEvent    *eventChoosen;						//The event choosen
	SimCompState    *nextCompState;						// Next state
	ProjectEvent    *reverseEvent;		
	SimCompState    *prevCompState;
	SimAlg			*sim;
	bool			eligEventComputed;
	bool			allEligEventFound;
	bool			nextStateComputed;
        
};
}

#endif
