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

#include<cassert>
#include<utility>
#include<algorithm>
#include "SimCompState.h"
#include "SimDebug.h"
#include "SimAlg.h"
#include <QString>

namespace DESpot
{

SimCompState::SimCompState(StateTuple& sta, SimAlg* simAlg):
	sim(simAlg)
{

    //dbg(QString("*** Init composite state given a global state vecot<StateTuple)"));
    currentState=StateTuple(sta);
	setStateType();
	reverseEvent=0;
	eventChoosen=0;
	prevCompState=0;
	nextCompState=0;
	eligEventComputed=false;
	allEligEventFound=false;
	nextStateComputed=false;

}

SimCompState::~SimCompState()
{
}

// NOTE! NOTE! NOTE! DO NOT call this function in any constructor of the
// class SimCompState as this function *new* SimCompState
// Algorithm:
void SimCompState::computeEligEventFlat(bool computeNextState)
{
	if(eligEventComputed) return;

	//QString debug_str;

    //dbg(QString("******** SimCompState::computeEligEvent ********"));
	//printState(&currentState);
    std::set<const ProjectEvent*> ev_sim = sim->getSimEvents();        // Events to SimAlg

	bool eligible=true;

    // We only compute the events we choosed
    std::set<const ProjectEvent*>::const_iterator it = ev_sim.begin();
    for(; it != ev_sim.end() ; ++it){
		const ProjectEvent* ev = *it;

		//QString eventName = QString::fromStdWString(ev->getName());

		// The Des where the ev is defined
		std::set<Des*> definedDesSet = sim->getDefinedDesSet(ev);  
		std::set<Des*> undefinedDesSet = sim->getUndefinedDesSet(ev);
		//std::set<DesEvent*> desEvSet = sim->getDesEventSet(ev);

		eligible=true;
		StateTuple nextState;

		ProjectEvent::SourceIteratorPtr srcIt = ev->createSourceIterator();
		for(srcIt->first(); srcIt->notDone(); srcIt->next())
		{
			const ProjectEvent::Source& src = srcIt->currentItem();
			Des *des = src.des;
			const DesEvent *desEvent=src.event;
			//dbg("  exame "+ldes->getName());
			DesState* state = currentState[des];

			/*
			debug_str=QString::fromStdWString(des->getName());
			debug_str.append("[");
			debug_str.append(QString::fromStdWString(state->getName()));
			debug_str.append(",");
			debug_str.append(eventName);
			*/

			DesState *destState=sim->getNextState(des,state,desEvent);
			if (destState){
				nextState.insert(std::make_pair(des,destState));

				//debug_str.append("] defined");
				//dbg(debug_str);
			}
			else {
				eligible=false;
				nextState.clear();
				
				//debug
				//debug_str.append("] notdefined - REJECTED");
				//dbg(debug_str);
				break;
			}
		}
		
		if (eligible) {
			/* get next state for the des that do not define this event.
			 * This is the same event, - selfloop
			 */

			// Feb/7/2009, we delay the next state compution for all cases now
			/*
			if (computeNextState)
			{
				std::set<Des*>::const_iterator des_it=undefinedDesSet.begin();
				for(; des_it != undefinedDesSet.end() ; ++des_it){
					Des* des = *des_it;
					DesState* state = currentState[des];
					nextState.insert(std::make_pair(des,state));
				}
				eligNextState.insert(std::make_pair(const_cast<ProjectEvent*>(ev),nextState));
			}
			*/


			// nextState is a local var, no need to delete
			//else
			//	delete nextState;
			eligEventSet.insert(const_cast<ProjectEvent*>(ev));

			
			//debug
			//dbg(QString("Event %1 ACCEPTED").arg(eventName));
			//printState(nextState);
		}
	}
	eligEventComputed=true;
	allEligEventFound=true;
	nextStateComputed=computeNextState;

}		

void SimCompState::computeEligEventHISC(bool computeAllEligEvent)
{
	if (computeAllEligEvent)
		computeEligEventHISCAll();
	else
		computeEligEventHISCLevelOptim();
}

//Same as level wise, only diff is getSimEvents
void SimCompState::computeEligEventSeqHISC()
{
	if(eligEventComputed) return;

	//QString debug_str;

	//Randomly choose a level
	std::set<const DesSubsystem*> levelSet1 =sim->getLevelSet();
	std::vector<const DesSubsystem*> levelSet(levelSet1.begin(),levelSet1.end());

	while (!levelSet.empty())
	{
		int maxRand = levelSet.size();
		/* initialize random seed: */
		qsrand ( QTime::currentTime().second() );
		/* generate secret number: */
		int idx = qrand() % maxRand;

		std::vector<const DesSubsystem*>::iterator levelIt = levelSet.begin()+idx;
		/*const DesSubsystem* level = */*levelIt;


		levelSet.erase(levelIt);
		
	
		//dbg(QString("******** SimCompState::computeEligEvent ********"));
		//printState(&currentState);
		std::set<const ProjectEvent*> ev_sim = sim->getSeqSimEvents();        // Events to SimAlg

		bool eligible=true;
		int found=0;

		// We only compute the events.
		std::set<const ProjectEvent*>::const_iterator it = ev_sim.begin();
		for(; it != ev_sim.end() ; ++it){
			const ProjectEvent* ev = *it;

			//QString eventName = QString::fromStdWString(ev->getName());

			// The Des where the ev is defined
			std::set<Des*> definedDesSet = sim->getDefinedDesSet(ev);  
			std::set<Des*> undefinedDesSet = sim->getUndefinedDesSet(ev);

			// Find in each des that the event is defined, if transition is
			// defined
			eligible=true;
			StateTuple nextState;

			ProjectEvent::SourceIteratorPtr srcIt = ev->createSourceIterator();
			for(srcIt->first(); srcIt->notDone(); srcIt->next())
			{
				const ProjectEvent::Source& src = srcIt->currentItem();

				//This should be level wise already
				Des *des = src.des;

				const DesEvent *desEvent=src.event;
				//dbg("  exame "+ldes->getName());
				DesState* state = currentState[des];

				/*
				debug_str=QString::fromStdWString(des->getName());
				debug_str.append("[");
				debug_str.append(QString::fromStdWString(state->getName()));
				debug_str.append(",");
				debug_str.append(eventName);
				*/

				DesState *destState=sim->getNextState(des,state,desEvent);
				if (destState){
					nextState.insert(std::make_pair(des,destState));

					//debug_str.append("] defined");
					//dbg(debug_str);
				}
				else {
					eligible=false;
					nextState.clear();
					
					//debug
					//debug_str.append("] notdefined - REJECTED");
					//dbg(debug_str);
					break;
				}
			}
			
			if (eligible) 
			{
				// get next state for the des that do not define this event.
				// This is the same event, - selfloop
				std::set<Des*>::const_iterator des_it=undefinedDesSet.begin();

				////// to optim, copy from the last state tuple
				for(; des_it != undefinedDesSet.end() ; ++des_it){
					Des* des = *des_it;
					DesState* state = currentState[des];
					nextState.insert(std::make_pair(des,state));
				}
				eligNextState.insert(std::make_pair(const_cast<ProjectEvent*>(ev),nextState));
				eligEventSet.insert(const_cast<ProjectEvent*>(ev));

				
				//debug
				//dbg(QString("Event %1 ACCEPTED").arg(eventName));
				//printState(nextState);

				found++;
			} //if eligible
		} // for event in the simEventSet

		/* debug only
		if(sim->isTraceEnabled()){
			QString line="Level=";
			line+=QString::fromStdWString(level->getName());
			line+=QString(" - %1 elig event found").arg(found);
			writeTrace(line);
		}
		*/

		if (found) break;  //if we found an ev at a level, we do not look into another

	}// while loop
	eligEventComputed=true;
	allEligEventFound=false;
	nextStateComputed=true;

}

// Compute all eligible states for HISC
// For slow mode and step by step mode
void SimCompState::computeEligEventHISCAll()
{
	if(eligEventComputed && allEligEventFound) return;

	//QString debug_str;
	std::set<const DesSubsystem*> recompLevelSet;

	//If in previous step, all elig events are computed
	//Optim 3 will make sense 
	if(reverseEvent && prevCompState->areAllEligEventsFound())
	{
		//We only need to re-calculate the levels that are impacted
		recompLevelSet = sim->getLevelSet(reverseEvent);

		/*
		// debug only
		if(sim->isTraceEnabled()){
			QString title = "Enter event = ";
			title += QString::fromStdWString(reverseEvent->getName());
			title += ". Levels to recalculate = ";
			printLevelSet(title,recompLevelSet);
		}
		*/

		//For other eligible events, we need to find the levels that control
		//it.  If that levels are not impacted, the eligibility is the same
		/* Feb/18/2009, now we cannot rely on getEligNextState
		std::map<ProjectEvent*,StateTuple>& prevEligNextState =
			prevCompState->getEligNextState();
		std::map<ProjectEvent*,StateTuple>::iterator it = prevEligNextState.begin();
		for(; it != prevEligNextState.end(); it++)
		{
			ProjectEvent *ev = it->first;
			if (!eventEligChanged(ev,recompLevelSet))
			{
				computeNextState(ev);
				eligEventSet.insert(const_cast<ProjectEvent*>(ev));
			}
		}
		*/
		std::set<ProjectEvent*>& prevEligEventSet =
		prevCompState->getEligEvents();

		std::set<ProjectEvent*>::iterator it = prevEligEventSet.begin();
		for(; it != prevEligEventSet.end(); it++)
		{
			ProjectEvent *ev = *it;
			if (!eventEligChanged(ev,recompLevelSet))
			{
				eligEventSet.insert(const_cast<ProjectEvent*>(ev));
			}
		}

	}
	else
	{
		recompLevelSet = sim->getLevelSet();
	}
	
	std::vector<const DesSubsystem*> levelSet(recompLevelSet.begin(),recompLevelSet.end());

	while (!levelSet.empty())
	{
		int maxRand = levelSet.size();
		/* initialize random seed: */
		qsrand ( QTime::currentTime().second() );
		/* generate secret number: */
		int idx = qrand() % maxRand;

		std::vector<const DesSubsystem*>::iterator levelIt = levelSet.begin()+idx;
		const DesSubsystem* level = *levelIt;
		//writeTrace(QString("Exam level:  %1").arg(QString::fromStdWString(level->getName())));


		levelSet.erase(levelIt);
			
		//dbg(QString("******** SimCompState::computeEligEvent ********"));
		//printState(&currentState);
		std::set<const ProjectEvent*> ev_sim = sim->getSimEvents(level);        // Events to SimAlg

		bool eligible=true;
		int found=0;

		// We only compute the events.
		std::set<const ProjectEvent*>::const_iterator it = ev_sim.begin();
		for(; it != ev_sim.end() ; ++it){
			const ProjectEvent* ev = *it;

			//QString eventName = QString::fromStdWString(ev->getName());

			// The Des where the ev is defined
			//std::set<Des*> definedDesSet = sim->getDefinedDesSet(ev,level);  
			//std::set<Des*> undefinedDesSet = sim->getUndefinedDesSet(ev,level);
			//std::set<DesEvent*> desEvSet = sim->getDesEventSet(ev);

			/* Find in each des that the event is defined, if transition is
			 * defined
			 */
			eligible=true;

			//StateTuple nextState;

			ProjectEvent::SourceIteratorPtr srcIt = ev->createSourceIterator();
			for(srcIt->first(); srcIt->notDone(); srcIt->next())
			{
				const ProjectEvent::Source& src = srcIt->currentItem();

				//This should be level wise already
				Des *des = src.des;

				//If this des is not in the current level, break

				const DesEvent *desEvent=src.event;
				//dbg("  exame "+ldes->getName());
				DesState* state = currentState[des];

				/*
				debug_str=QString::fromStdWString(des->getName());
				debug_str.append("[");
				debug_str.append(QString::fromStdWString(state->getName()));
				debug_str.append(",");
				debug_str.append(eventName);
				*/

				DesState *destState=sim->getNextState(des,state,desEvent);
				if (destState){
					//nextState.insert(std::make_pair(des,destState));

					//debug_str.append("] defined");
					//dbg(debug_str);
				}
				else {
					eligible=false;
					//nextState.clear();
					
					//debug
					//debug_str.append("] notdefined - REJECTED");
					//dbg(debug_str);
					//writeTrace(QString("Event %1 rejected").arg(QString::fromStdWString(ev->getName())));
					break;
				}
			}
			
			if (eligible) 
			{
				/* get next state for the des that do not define this event.
				 * This is the same event, - selfloop
				 */

				// Feb/7/2009 delay the compute of next state 
				/*
				std::set<Des*>::const_iterator des_it=undefinedDesSet.begin();

				////// to optim, copy from the last state tuple
				for(; des_it != undefinedDesSet.end() ; ++des_it){
					Des* des = *des_it;
					DesState* state = currentState[des];
					nextState.insert(std::make_pair(des,state));
				}
				eligNextState.insert(std::make_pair(const_cast<ProjectEvent*>(ev),nextState));
				*/
				eligEventSet.insert(const_cast<ProjectEvent*>(ev));
				
				//debug
				//dbg(QString("Event %1 ACCEPTED").arg(QString::fromStdWString(ev->getName())));
				//printState(&nextState);

				found++;
			} //if eligible
		} // for event in the simEventSet

		/* debug only
		if(sim->isTraceEnabled()){
			QString line="Level=";
			line+=QString::fromStdWString(level->getName());
			line+=QString(" - %1 elig event found").arg(found);
			writeTrace(line);
		}
		*/

		//We need to find all eligile event
		//if (found) break;  

	}// while loop
	eligEventComputed=true;
	allEligEventFound=true;
	nextStateComputed=false;

}


//Here we stop when we find elig events in a level
//Optim - do not compute next state 
void SimCompState::computeEligEventHISCLevelOptim()
{
	if(eligEventComputed) return;

	//QString debug_str;

	//Randomly choose a level
	std::set<const DesSubsystem*> levelSet1 =sim->getLevelSet();
	std::vector<const DesSubsystem*> levelSet(levelSet1.begin(),levelSet1.end());

	while (!levelSet.empty())
	{
		int maxRand = levelSet.size();
		/* initialize random seed: */
		qsrand ( QTime::currentTime().second() );
		/* generate secret number: */
		int idx = qrand() % maxRand;

		std::vector<const DesSubsystem*>::iterator levelIt = levelSet.begin()+idx;
		const DesSubsystem* level = *levelIt;
		levelSet.erase(levelIt);
		
		//dbg(QString("******** SimCompState::computeEligEvent ********"));
		//printState(&currentState);
		std::set<const ProjectEvent*> ev_sim = sim->getSimEvents(level);        // Events to SimAlg

		bool eligible=true;
		int found=0;

		// We only compute the events.
		std::set<const ProjectEvent*>::const_iterator it = ev_sim.begin();
		for(; it != ev_sim.end() ; ++it){
			const ProjectEvent* ev = *it;

			//QString eventName = QString::fromStdWString(ev->getName());

			// The Des where the ev is defined
			//std::set<Des*> definedDesSet = sim->getDefinedDesSet(ev,level);  
			//std::set<Des*> undefinedDesSet = sim->getUndefinedDesSet(ev,level);
			//std::set<Des*> definedDesSet = sim->getDefinedDesSet(ev);  
			//std::set<Des*> undefinedDesSet = sim->getUndefinedDesSet(ev);

			//std::set<DesEvent*> desEvSet = sim->getDesEventSet(ev);

			eligible=true;

			ProjectEvent::SourceIteratorPtr srcIt = ev->createSourceIterator();
			for(srcIt->first(); srcIt->notDone(); srcIt->next())
			{
				const ProjectEvent::Source& src = srcIt->currentItem();

				//This should be level wise already
				Des *des = src.des;
				const DesEvent *desEvent=src.event;
				DesState* state = currentState[des];

				//dbg("  exame "+ldes->getName());
				//debug_str=QString::fromStdWString(des->getName());
				//debug_str.append("[");
				//debug_str.append(QString::fromStdWString(state->getName()));
				//debug_str.append(",");
				//debug_str.append(eventName);

				DesState *destState=sim->getNextState(des,state,desEvent);
				if (destState==0)
				{
					eligible=false;
					break;
				}
			}
			
			if (eligible) 
			{
				eligEventSet.insert(const_cast<ProjectEvent*>(ev));			
				found++;
			} //if eligible
		} // for event in the simEventSet

		// debug only
		/*
		if(sim->isTraceEnabled()){
			QString line="Level=";
			line+=QString::fromStdWString(level->getName());
			line+=QString(" - %1 elig event found").arg(found);
			writeTrace(line);
			printEligEvents();
		}
		*/
		

		if (found) break;  //if we found an ev at a level, we do not look into another

	}// while loop
	eligEventComputed=true;
	allEligEventFound=false;
	nextStateComputed=false;
}

bool SimCompState::isNextStateComputed(const ProjectEvent* projEvent)
{
	if(eligNextState.count(const_cast<ProjectEvent*>(projEvent))>0)
		return true;
	else
		return false;
}

void SimCompState::computeNextState(const ProjectEvent* projEvent)
{
	//if (nextStateComputed)
	if(isNextStateComputed(projEvent))
		return;

	std::set<Des*> undefinedDesSet = sim->getUndefinedDesSet(projEvent);

	StateTuple nextState;

	//The set is the same as the result of getDefinedDesSet(ev)
	ProjectEvent::SourceIteratorPtr srcIt = projEvent->createSourceIterator();
	for(srcIt->first(); srcIt->notDone(); srcIt->next())
	{
		const ProjectEvent::Source& src = srcIt->currentItem();

		//This should be level wise already
		Des *des = src.des;
		const DesEvent *desEvent=src.event;
		DesState* state = currentState[des];

		DesState *destState=sim->getNextState(des,state,desEvent);
		nextState.insert(std::make_pair(des,destState));
	}

	// to optim, copy from the last state tuple
	std::set<Des*>::const_iterator des_it=undefinedDesSet.begin();
	for(; des_it != undefinedDesSet.end() ; ++des_it)
	{
		Des* des = *des_it;
		DesState* state = currentState[des];
		nextState.insert(std::make_pair(des,state));
	}
	
	eligNextState.insert(std::make_pair(const_cast<ProjectEvent*>(projEvent),nextState));

}

void SimCompState::computeNextStateHISC(const ProjectEvent* projEvent)
{
	if(isNextStateComputed(projEvent))
		return;

	std::set<Des*> undefinedDesSet = sim->getUndefinedDesSet(projEvent);

	StateTuple nextState;

	//The set is the same as the result of getDefinedDesSet(ev)
	ProjectEvent::SourceIteratorPtr srcIt = projEvent->createSourceIterator();
	for(srcIt->first(); srcIt->notDone(); srcIt->next())
	{
		const ProjectEvent::Source& src = srcIt->currentItem();

		//This should be level wise already
		Des *des = src.des;
		const DesEvent *desEvent=src.event;
		DesState* state = currentState[des];

		DesState *destState=sim->getNextState(des,state,desEvent);
		nextState.insert(std::make_pair(des,destState));
	}

	// to optim, copy from the last state tuple
	std::set<Des*>::const_iterator des_it=undefinedDesSet.begin();
	for(; des_it != undefinedDesSet.end() ; ++des_it)
	{
		Des* des = *des_it;
		DesState* state = currentState[des];
		nextState.insert(std::make_pair(des,state));
	}
	
	eligNextState.insert(std::make_pair(const_cast<ProjectEvent*>(projEvent),nextState));

}

//To find all eligible event in HISC
//optimization 3th
/**************************************************************************
     3)  For HISC as HISC simulation in slow mode [or after a user
         specified event], we have to provide a list of eligible events.  We
         can use HISC  conditions to speed this up by easily determining events
         whose eligibility condition would be unchanged. If the last
         chosen event [to occur] did not affect a given level (no DES
         for the level, including its interface,  care about this
         event) (note: all interface events [req, answer and low data
         events] always affect the high level), then the eligibility
         of the events that this level controls has not changed 
         and remain the same, so you do not need to recalculate them, just
         re-use from last time [even though DES that contain this
         event may have changed state on another level].  For a flat
         system, we would have recalculate eveery event for which a
         DES that contains this event changed state.  This means at
         most two levels will be affected (possibly only one for high
         or low events) for any given event, and only the events they
         control need to be rechecked for eligibility.  This should
         speed up the eligibility check for large HISC system
*********************************************************************/
void SimCompState::printLevelSet(QString title, std::set<const DesSubsystem*>& levelSet)
{

	QString line = title;
	std::set<const DesSubsystem*>::iterator impactIt = levelSet.begin();
	for (; impactIt != levelSet.end(); impactIt++){
		line += QString::fromStdWString((*impactIt)->getName());
		line += ",";
	}
	line.remove(line.count()-1,1);
	writeTrace(line);
}
	


void SimCompState::printState(StateTuple* sta)
{
	QString line;
    StateTuple::const_iterator it=sta->begin();
    for(; it != sta->end() ; ++it){
		Des* des = (it->first);
		DesState* state = (it->second);
		line += QString::fromStdWString(des->getName());
		line += "[";
		line += QString::fromStdWString(state->getName());
		line += "]-";
	}
	line.remove(line.count()-1,1);
	writeTrace(line);
}

void SimCompState::printShortState(QString title)
{
	QString line=title;
	line += ": ";
	if (isInit())
		//line += "@";
		line += "[I]";
	if (isMarked())
		//line += "*";
		line += "[M]";
	line += "[";
    StateTuple::const_iterator it = currentState.begin();
    for(; it != currentState.end() ; ++it){
		/*Des* des = */(it->first);
		DesState* state = (it->second);
		if (state->isInit())
			line += '^';
		if (state->isMarked())
			line += '*';
		line += QString::fromStdWString(state->getName());
		line += ",";
	}
	line.remove(line.count()-1,1);
	line += "]";
	writeTrace(line);
}

void SimCompState::printLongState(QString title)
{
	QString line=title;
	line += ": ";
	if (isInit())
		//line += "@";
		line += "[I]";
	if (isMarked())
		//line += "*";
		line += "[M]";
	line += "[";
    StateTuple::const_iterator it = currentState.begin();
    for(; it != currentState.end() ; ++it){
		Des* des = (it->first);
		DesState* state = (it->second);
		if (state->isInit())
			line += '^';
		if (state->isMarked())
			line += '*';
		line += QString::fromStdWString(des->getName());
		line += "/";
		line += QString::fromStdWString(state->getName());
		line += ",";
	}
	line.remove(line.count()-1,1);
	line += "]";
	writeTrace(line);
}

void SimCompState::printEligEvents()
{
	QString line;
	if(allEligEventFound)
		line += "Eligible events: [";
	else
		line += "Eligible events for the chosen level: [";

	/*
	std::map<ProjectEvent*,StateTuple>::iterator it = eligNextState.begin();
	while (it != eligNextState.end()){
		ProjectEvent* ev = it->first;
		line += QString::fromStdWString(ev->getName());
		line += ",";
		it++;
	}
	line.remove(line.count()-1,1);
	line += "]";
	writeTrace(line);
	*/

	std::set<ProjectEvent*>::iterator it = eligEventSet.begin();
	while (it != eligEventSet.end()){
		ProjectEvent* ev = *it;
		line += QString::fromStdWString(ev->getName());
		line += ",";
		it++;
	}
	line.remove(line.count()-1,1);
	line += "]";
	writeTrace(line);
}


SimCompState::StateTuple SimCompState::getInitGlobalState(const DesProject* proj)
{
	DesProject::DesIteratorPtr desIt = proj->createDesIterator();
	SimCompState::StateTuple gstate;

	for(desIt->first(); desIt->isDone() == false; desIt->next())
	{
		const Des& des = desIt->currentItem();	
		const DesState* sta = &(des.getInitialState());;
		Des* pDes = const_cast<Des*>(&des);
		gstate[pDes] = const_cast<DesState*>(sta);
	}
	return gstate;
}

void SimCompState::dbg(QString str)
{
	sim->dbg(str);
	str.clear();
}

void SimCompState::writeTrace(QString str)
{
	sim->dbg(str);
}

std::set<ProjectEvent*>& SimCompState::getEligEvents()
{
	return eligEventSet;

/* Above is an optimization
	std::set<ProjectEvent*> eligibleEventSet;

	std::map<ProjectEvent*,StateTuple>::iterator it = eligNextState.begin();
	while (it != eligNextState.end()){
		eligibleEventSet.insert(it->first);
		it++;
	}
    
	return eligibleEventSet;
*/
}

/*
std::set<Des*> SimCompState::getEventDesSet(const ProjectEvent* event)
{
	switch(event->getType())
	{
        case eAnswerEvent:
        case eRequestEvent:
        case eLDataEvent:
			return getEventDesSet(static_cast<const InterfaceEvent*>(event));

        case eHighLevelEvent:
        case eLowLevelEvent:
			return getEventDesSet(static_cast<const SubsystemEvent*>(event));

		default:
			assert(false);
			throw EX("Invalid event type. Cannot set type of event.")
	}
}


std::set<Des*> SimCompState::getEventDesSet(const InterfaceEvent* interfEvent)
{
	std::set<Des*> desSet;
	if (interfEvent->hasOwner())
		const DesInterface& interf = interfEvent->owner();
	else
		//This is an orphaned interface event. This means that it
		//is used in subsystems but not defined in any interface in
		//the project. The orphaned events are displayed at the
		//root of all interface events signifying that they do not
		//belong to any interface
		return desSet;
	return desSet;
} 

std::set<Des*> SimCompState::getEventDesSet(const SubsystemEvent* subsysEvent)
{
	const DesSubsystem& subsys = subsysEvent->owner();

	std::set<Des*> desSet;
	return desSet;
}
*/

SimCompState::StateTuple SimCompState::getNextStateTuple(ProjectEvent* ev)
{
	//if (!nextStateComputed)
	if(!isNextStateComputed(ev))
		computeNextState(ev);
	StateTuple tuple = eligNextState[ev];
	return eligNextState[ev];
}

void SimCompState::setStateType()
{
	std::map<Des*,DesState*>::const_iterator it = currentState.begin();
	initState = true;
	markedState = true;
	for (; it != currentState.end(); ++it){
		/*Des* des = */it->first;
		DesState* state = it->second;
		if (!state->isInit()){
			initState = false;
			break;
		}
	}

	it = currentState.begin();
	for (; it != currentState.end(); ++it){
		/*Des* des = */it->first;
		DesState* state = it->second;
		if (!state->isMarked()){
			markedState = false;
			break;
		}
	}
	
	//debug
	//if(markedState)
      //writeTrace("&&&&&&&&&THIS IS MARKED STATE&&&&&&&&&&");
}

//Check if we can reuse the eligible events from the last state tuple
//This is an optim of computing all elig events in HISC mode
bool SimCompState::eventEligChanged(ProjectEvent* ev, std::set<const DesSubsystem*> &recompLevelSet)
{
	bool eligChanged = false;

	//bug: this should be the level the event controls, i.e, not impacted
	//fix: add eventLevelCtlMap
	//std::set<const DesSubsystem*> impactedLevelSet = sim->getLevelSet(ev);
	const DesSubsystem* controlLevel = sim->getCtlLevelSet(ev);

	if (recompLevelSet.count(controlLevel)>0)
		eligChanged = true;
	else
		eligChanged = false;

	/*
	if(sim->isTraceEnabled())
		if (eligChanged == false)
			{
				QString title = "Prev event = ";
				title += QString::fromStdWString(ev->getName());
				//title += " : eligibility not change. level = ";
				//printLevelSet(title,impactedLevelSet);
				title += QString(" : eligibility not change. level = %1").arg(QString::fromStdWString(controlLevel->getName()));
				writeTrace(title);
			}
		else
			{
				QString title = "Prev event = ";
				title += QString::fromStdWString(ev->getName());
				//title += " eligibility changed. level = ";
				//printLevelSet(title,impactedLevelSet);
				title += QString(" : eligibility not change. level = %1").arg(QString::fromStdWString(controlLevel->getName()));
				writeTrace(title);
			}
	*/

	return eligChanged;
}


}
