/*	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
*/

#include "TransRecorder.h"

namespace DESpot
{

const QString TransRecorder::cRecordingStartedMsg = "<br>Transition recording has started";
const QString TransRecorder::cStartStateMsg = "Start State = ";
const QString TransRecorder::cSelectStartStateStatus = "Please select the start state from the state list...";
const QString TransRecorder::cRecordingStoppedMsg = "<br>Transition recording was stopped";
const QString TransRecorder::cEventLabelMsg = "%1<br>Event Label = ";
const QString TransRecorder::cSelectEventStatus = "Please select an event from the event list...";
const QString TransRecorder::cTransRecordedMsg = "<br><font color=\"green\">Transition ( %1 ; %2 ; %3 ) has been recorded</font><br><br>";
const QString TransRecorder::cRecordingCancelErr = "<br><font color=\"red\">Recording is being cancelled: events occurred in the wrong order</font>";
const QString TransRecorder::cEndStateMsg = "%1<br>End State = ";
const QString TransRecorder::cSelectEndStateStatus = "Please select the end state from the state list...";

TransRecorder::TransRecorder(): m_recState(eNotRecording)
{
}

//_________________________________________________________________________________________________

TransRecorder::~TransRecorder(void)
{
}

//_________________________________________________________________________________________________

void TransRecorder::init(QStatusBar* statusBar)
{
	m_statusBar = statusBar;
}

//_________________________________________________________________________________________________

void TransRecorder::initEventListWidget(EventViewerWidget* widget)
{
	m_eventListWidg = widget;
}

//_________________________________________________________________________________________________

void TransRecorder::initStateListWidget(StateViewerWidget* widget)
{
	m_stateListWidg = widget;
}

//_________________________________________________________________________________________________

void TransRecorder::initOutputUi(DesEditorOutputUiPart* outUi)
{
	m_outUi = outUi;
}

void TransRecorder::initOutputUi(GedDesEditorOutputUiPart* /*outUi*/)
{
//	m_outUi = outUi;
}
//_________________________________________________________________________________________________

void TransRecorder::startRecording()
{
	m_stateListWidg->clearSelection();
	connect(m_stateListWidg, SIGNAL(onStateClicked(const DesState&)), 
		    this, SLOT(onStateSelected(const DesState&))) ;

	m_eventListWidg->clearSelection();
	connect(m_eventListWidg, SIGNAL(onEventClicked(const DesEvent&)), 
		    this, SLOT(onEventSelected(const DesEvent&))) ;

	m_recState = eRecordFromState;	

	m_outUi->writeLine(cRecordingStartedMsg);
	m_outUi->write(cStartStateMsg);
	m_statusBar->showMessage(cSelectStartStateStatus);			
}

//_________________________________________________________________________________________________

void TransRecorder::stopRecording()
{
	disconnect(m_stateListWidg, SIGNAL(onStateClicked(const DesState&)), 
		       this, SLOT(onStateSelected(const DesState&))) ;

	disconnect(m_eventListWidg, SIGNAL(onEventClicked(const DesEvent&)), 
			   this, SLOT(onEventSelected(const DesEvent&))) ;

	m_recState = eNotRecording;
	
	m_outUi->writeLine(cRecordingStoppedMsg);
}

//_________________________________________________________________________________________________

void TransRecorder::toggleRecording()
{
	if (isRecording())
	{
		stopRecording();
	}
	else
	{
		startRecording();
	}
}

//_________________________________________________________________________________________________

bool TransRecorder::isRecording()
{
	return m_recState != eNotRecording;
}

//_________________________________________________________________________________________________

TransRecorder::RecState TransRecorder::nextState()
{
	switch(m_recState)
	{
		case eRecordFromState:
			m_recState = eRecordEvent;
			break;

		case eRecordEvent:
			m_recState = eRecordToState;
			break;

		case eRecordToState:
			m_recState = eRecordFromState;
			break;

		default:
			assert(false); //no change
	}

	return m_recState;
}

//_________________________________________________________________________________________________

void TransRecorder::onStateSelected(const DesState& state)
{
	switch(m_recState)
	{
		case eRecordFromState:
		{
			//record the "from state"
			m_trans.setFromState(state);

			//output the operation
			QString msg(cEventLabelMsg);
			m_outUi->write(msg.arg(QString::fromStdWString(state.getName())));
			m_statusBar->showMessage(cSelectEventStatus);

			//advance to the next state
			nextState();
			break;
		}

		case eRecordToState:
		{
			//record the "to state"
			m_trans.setToState(state);

			//output the operation			
			m_outUi->writeLine(QString::fromStdWString(state.getName()));
			m_outUi->write(cTransRecordedMsg.arg(QString::fromStdWString(m_trans.fromState().getName()), 
												 QString::fromStdWString(m_trans.event().getName()),
												 QString::fromStdWString(m_trans.toState().getName())));
			m_outUi->write(cStartStateMsg); 
			m_statusBar->showMessage(cSelectStartStateStatus);			

			//notify the editor that a transition has been recorded
			emit transitionRecorded(m_trans);

			//advance to the next state
			nextState();
			break;
		}

		default:
			//wrong recording state
			m_outUi->write(cRecordingCancelErr);
			stopRecording();
			emit recordingCancelled();
	}
	
}

//_________________________________________________________________________________________________

void TransRecorder::onEventSelected(const DesEvent& event)
{
	if (m_recState == eRecordEvent)
	{
		m_trans.setEvent(event);
		
		m_outUi->write(cEndStateMsg.arg(QString::fromStdWString(event.getName())));
		m_statusBar->showMessage(cSelectEndStateStatus);
		nextState();
	}
	else
	{
		//wrong recording state
		m_outUi->write(cRecordingCancelErr);
		stopRecording();
		emit recordingCancelled();
	}
}

} //end of namespace DESpot
