/**
	hsmCommunicator.c

	This file automatically generated by FSMLang
*/

#include "hsmCommunicator_priv.h"
#include <stddef.h>

#ifndef DBG_PRINTF
#define DBG_PRINTF(...)
#endif

extern HSM_COMMUNICATOR_SUB_FSM_IF hsmCommunicator_establishSession_sub_fsm_if;
extern HSM_COMMUNICATOR_SUB_FSM_IF hsmCommunicator_sendMessage_sub_fsm_if;

static HSM_COMMUNICATOR_EVENT IDLE_stateFn(pHSM_COMMUNICATOR,HSM_COMMUNICATOR_EVENT);
static HSM_COMMUNICATOR_EVENT ESTABLISHING_SESSION_stateFn(pHSM_COMMUNICATOR,HSM_COMMUNICATOR_EVENT);
static HSM_COMMUNICATOR_EVENT IN_SESSION_stateFn(pHSM_COMMUNICATOR,HSM_COMMUNICATOR_EVENT);
static const HSM_COMMUNICATOR_STATE_FN hsmCommunicator_state_fn_array[hsmCommunicator_numStates] = 
{
	  IDLE_stateFn
	, ESTABLISHING_SESSION_stateFn
	, IN_SESSION_stateFn
};


const pHSM_COMMUNICATOR_SUB_FSM_IF hsmCommunicator_sub_fsm_if_array[THIS(numSubMachines)] =
{
	&hsmCommunicator_establishSession_sub_fsm_if
	, &hsmCommunicator_sendMessage_sub_fsm_if
};

HSM_COMMUNICATOR hsmCommunicator = {
	hsmCommunicator_IDLE,
	THIS(SEND_MESSAGE),
	&hsmCommunicator_state_fn_array,
	&hsmCommunicator_sub_fsm_if_array,
	hsmCommunicatorFSM
};

pHSM_COMMUNICATOR phsmCommunicator = &hsmCommunicator;

void run_hsmCommunicator(HSM_COMMUNICATOR_EVENT e)
{
	if (phsmCommunicator)
	{
		phsmCommunicator->fsm(phsmCommunicator,e);
	}
}

static HSM_COMMUNICATOR_EVENT findAndRunSubMachine(pHSM_COMMUNICATOR,HSM_COMMUNICATOR_EVENT);


#ifndef EVENT_IS_NOT_EXCLUDED_FROM_LOG
#define EVENT_IS_NOT_EXCLUDED_FROM_LOG(e) ((e) == (e))
#endif
void hsmCommunicatorFSM(pHSM_COMMUNICATOR pfsm, HSM_COMMUNICATOR_EVENT event)
{
	HSM_COMMUNICATOR_EVENT e = event;

	while (e != hsmCommunicator_noEvent) {

#ifdef HSM_COMMUNICATOR_DEBUG
if (EVENT_IS_NOT_EXCLUDED_FROM_LOG(e))
{
	DBG_PRINTF("event: %s; state: %s"
,HSM_COMMUNICATOR_EVENT_NAMES[e]
,HSM_COMMUNICATOR_STATE_NAMES[pfsm->state]
);
}
#endif

	/* This is read-only data to facilitate error reporting in action functions */
	pfsm->event = e;

		if (e < hsmCommunicator_noEvent)
		{
			e = ((* (*pfsm->statesArray)[pfsm->state])(pfsm,e));
		}
		else
		{
			e = findAndRunSubMachine(pfsm, e);
		}

	}
}


static HSM_COMMUNICATOR_EVENT findAndRunSubMachine(pHSM_COMMUNICATOR pfsm, HSM_COMMUNICATOR_EVENT e)
{
	for (HSM_COMMUNICATOR_SUB_MACHINES machineIterator = THIS(firstSubMachine);
	     machineIterator < THIS(numSubMachines);
	     machineIterator++
	    )
	{
			if (
			   ((*pfsm->subMachineArray)[machineIterator]->first_event <= e)
			   && ((*pfsm->subMachineArray)[machineIterator]->last_event >= e)
			    )
			{
				return ((*(*pfsm->subMachineArray)[machineIterator]->subFSM)(e));
			}
	}

	return THIS(noEvent);

}

static HSM_COMMUNICATOR_EVENT IDLE_stateFn(pHSM_COMMUNICATOR pfsm,HSM_COMMUNICATOR_EVENT e)
{
	HSM_COMMUNICATOR_EVENT retVal = THIS(noEvent);

	switch(e)
	{
	case THIS(SEND_MESSAGE):
		retVal = UFMN(startSessionEstablishment)(pfsm);
		pfsm->state = hsmCommunicator_ESTABLISHING_SESSION;
		break;
	default:
		DBG_PRINTF("hsmCommunicator_noAction");
		break;
	}

	return retVal;
}

static HSM_COMMUNICATOR_EVENT ESTABLISHING_SESSION_stateFn(pHSM_COMMUNICATOR pfsm,HSM_COMMUNICATOR_EVENT e)
{
	HSM_COMMUNICATOR_EVENT retVal = THIS(noEvent);

	switch(e)
	{
	case THIS(SEND_MESSAGE):
		retVal = UFMN(requestMessageTransmission)(pfsm);
		break;
	case THIS(SESSION_ESTABLISHED):
		retVal = UFMN(completeSessionStart)(pfsm);
		pfsm->state = hsmCommunicator_IN_SESSION;
		break;
	case THIS(SESSION_TIMEOUT):
		retVal = UFMN(notifySessionTimeout)(pfsm);
		pfsm->state = hsmCommunicator_IDLE;
		break;
	default:
		DBG_PRINTF("hsmCommunicator_noAction");
		break;
	}

	return retVal;
}

static HSM_COMMUNICATOR_EVENT IN_SESSION_stateFn(pHSM_COMMUNICATOR pfsm,HSM_COMMUNICATOR_EVENT e)
{
	HSM_COMMUNICATOR_EVENT retVal = THIS(noEvent);

	switch(e)
	{
	case THIS(SEND_MESSAGE):
		retVal = UFMN(requestMessageTransmission)(pfsm);
		break;
	case THIS(SESSION_TIMEOUT):
		retVal = UFMN(notifySessionTimeout)(pfsm);
		pfsm->state = hsmCommunicator_IDLE;
		break;
	default:
		DBG_PRINTF("hsmCommunicator_noAction");
		break;
	}

	return retVal;
}


HSM_COMMUNICATOR_EVENT __attribute__((weak)) UFMN(startSessionEstablishment)(FSM_TYPE_PTR pfsm)
{
	DBG_PRINTF("weak: %s", __func__);
	(void) pfsm;
	return THIS(noEvent);
}

HSM_COMMUNICATOR_EVENT __attribute__((weak)) UFMN(completeSessionStart)(FSM_TYPE_PTR pfsm)
{
	DBG_PRINTF("weak: %s", __func__);
	(void) pfsm;
	return THIS(noEvent);
}

HSM_COMMUNICATOR_EVENT __attribute__((weak)) UFMN(notifySessionTimeout)(FSM_TYPE_PTR pfsm)
{
	DBG_PRINTF("weak: %s", __func__);
	(void) pfsm;
	return THIS(noEvent);
}

HSM_COMMUNICATOR_EVENT __attribute__((weak)) UFMN(requestMessageTransmission)(FSM_TYPE_PTR pfsm)
{
	DBG_PRINTF("weak: %s", __func__);
	(void) pfsm;
	return THIS(noEvent);
}


#ifdef HSM_COMMUNICATOR_DEBUG
char *HSM_COMMUNICATOR_EVENT_NAMES[] = {
	 "hsmCommunicator_SEND_MESSAGE"
	,"hsmCommunicator_SESSION_ESTABLISHED"
	,"hsmCommunicator_SESSION_TIMEOUT"
	, "hsmCommunicator_noEvent"
	, "hsmCommunicator_numEvents"
	, "hsmCommunicator_establishSession_ESTABLISH_SESSION_REQUEST"
	, "hsmCommunicator_establishSession_STEP0_RESPONSE"
	, "hsmCommunicator_establishSession_STEP1_RESPONSE"
	, "hsmCommunicator_establishSession_noEvent"
	, "hsmCommunicator_sendMessage_SEND_MESSAGE"
	, "hsmCommunicator_sendMessage_ACK"
	, "hsmCommunicator_sendMessage_SESSION_ESTABLISHED"
	, "hsmCommunicator_sendMessage_SESSION_TIMEOUT"
	, "hsmCommunicator_sendMessage_noEvent"
};

char *HSM_COMMUNICATOR_STATE_NAMES[] = {
	 "hsmCommunicator_IDLE"
	,"hsmCommunicator_ESTABLISHING_SESSION"
	,"hsmCommunicator_IN_SESSION"
};

#endif