// WMStateMachine.cpp: implementation of the WMStateMachine class.
//
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000 Robert Cunnings. All rights reserved.
//
// You may copy, modify, distribute or publish this code free of charge.
//
// NO WARRANTY: This software is provided AS IS, without warranty of any kind.
//
//////////////////////////////////////////////////////////////////////
//
// WMStateMachine class - a class for finite state machine implementation.
// 
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "WMStateMachine.h"
#include "WMEventHandler.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

WMStateMachine::WMStateMachine()
{

}

WMStateMachine::~WMStateMachine()
{
	for (mapKeyToTransition::iterator iM = m_TransitionMap.begin();
			iM != m_TransitionMap.end();
			iM++)
	{
		LPTRANSITION pTran = (*iM).second;
		if (pTran != NULL)
		{
			free(pTran);
		}
	}
	m_TransitionMap.clear();
}

void WMStateMachine::Initialize(int nState, WMEventHandler *pHandler)
{
	m_nState = nState;
	m_pHandler = pHandler;
}

void WMStateMachine::Transition(int nEvent)
{
	int nCurrentEvent = nEvent;

	while (nCurrentEvent != EV_NULL_EVENT)
	{
		// look up transition structure
		mapKeyToTransition::iterator iM = m_TransitionMap.find((nCurrentEvent << 16) + m_nState);
		if (iM == m_TransitionMap.end())
		{
			// unregistered transition
			// consume event
			break;
		}
		else
		{
			LPTRANSITION pTran = (*iM).second;
			// run event handler
			nCurrentEvent = m_pHandler->HandleEvent(pTran->TransIndex);
			// change state
			m_nState = pTran->DestState;
		}
	}
}

BOOL WMStateMachine::RegisterTransition(int nSourceState,
											int nDestState,
											int nEvent,
											int nTransIndex)
{
	LPTRANSITION pTrans = (LPTRANSITION)malloc(sizeof(TRANSITION));
	if (pTrans == NULL)
		return FALSE;
	pTrans->SourceState = nSourceState;
	pTrans->DestState = nDestState;
	pTrans->Event = nEvent;
	pTrans->TransIndex = nTransIndex;
	// create key
	int nKey = (nEvent << 16) + nSourceState;
	// insert in map
	m_TransitionMap.insert(mapKeyToTransition::value_type(nKey, pTrans));
	return TRUE;
}