#include "RTDS_Startup_decl.h"
#include "bLocal.h"


/*
 * FUNCTION FOR PROCESS pLocal:
 * ----------------------------
 */

void pLocal(RTDS_GlobalProcessInfo *RTDS_currentContext)
	{
	char                            *pCardId,*pCodeId,*pKey;
	int                                lengthCardId, lengthCodeId, lenMsg,lengthKey;
	tCardAndCode          *pCardAndCode;
	short                           mode;
	/* *************************************************************** */
	/* $(RTDS_HOME)/share/ccg/vxworks/bricks/RTDS_Proc_begin.c begins */
	/* Copyright (C) 2002 PragmaDev */

	int 					RTDS_sdlStatePrev = 0;
	RTDS_MessageHeader		*RTDS_readSaveQueue = NULL, *RTDS_writeSaveQueue = NULL;
	RTDS_TimerState 		*RTDS_timer, *RTDS_prevTimer;
	RTDS_QueueId			RTDS_senderQueueId = NULL;

	/* To synchronize processes at startup time */
	RTDS_START_SYNCHRO_WAIT;

	/* $(RTDS_HOME)/share/ccg/vxworks/bricks/RTDS_Proc_begin.c ends */
	/* ************************************************************ */


	/* Initial transition */
	Display(msgEnterCard, RTDS_currentContext);
	mode=NORMAL;
	RTDS_SDL_STATE_SET(idle);
	/* Event loop */
	for ( ; ; )
		{
		/* *************************************************************** */
		/* $(RTDS_HOME)/share/ccg/vxworks/bricks/RTDS_Proc_middle.c begins */
		/* Copyright (C) 2002 PragmaDev */

		/* Check saved messages */
		if ( RTDS_readSaveQueue != NULL )
			{
			RTDS_currentContext->currentMessage = RTDS_readSaveQueue;
			RTDS_readSaveQueue = RTDS_readSaveQueue->next;
			}
		/* If no saved messages left, get message from process's message queue */
		else
			{
			RTDS_currentContext->currentMessage = (RTDS_MessageHeader *)RTDS_MALLOC(sizeof(RTDS_MessageHeader));
			RTDS_MSG_QUEUE_READ(RTDS_currentContext->currentMessage);
			RTDS_currentContext->currentMessage->next = NULL;
			}
		
		/* Discard cancelled timers */
		if ( RTDS_currentContext->currentMessage->timerUniqueId != 0 )
			{
			RTDS_senderQueueId = RTDS_currentContext->currentMessage->sender;
			RTDS_prevTimer = NULL;
			for ( RTDS_timer = RTDS_currentContext->timerList ; RTDS_timer != NULL; RTDS_timer = RTDS_timer->next )
				{
				/* If timer found and cancelled */
				if ( RTDS_timer->timerUniqueId == RTDS_currentContext->currentMessage->timerUniqueId )
					{
					if ( RTDS_timer->state == RTDS_TIMER_CANCELLED )
						{
						/* Discard current message */
						RTDS_FREE(RTDS_currentContext->currentMessage);
						RTDS_currentContext->currentMessage = NULL;
						}

					/* Remove it from list of timers */
					if ( RTDS_prevTimer == NULL )
						{
						RTDS_currentContext->timerList = RTDS_currentContext->timerList->next;
						}
					else
						{
						RTDS_prevTimer->next = RTDS_timer->next;
						}
					RTDS_FREE(RTDS_timer);
					break;
					}
				RTDS_prevTimer = RTDS_timer;
				}
			}

		/* Let's process the message ! */
		if ( RTDS_currentContext->currentMessage != NULL )
			{
			#ifdef RTDS_SIMULATOR
				RTDS_SIMULATOR_TRACE(RTDS_messageReceived, RTDS_currentContext->currentMessage, SELF);
				/* Release the message unique id back to the pool */
				RTDS_ReleaseMessageUniqueId(RTDS_currentContext->currentMessage->messageUniqueId);
			#endif
			RTDS_senderQueueId = RTDS_currentContext->currentMessage->sender;
			RTDS_sdlStatePrev = RTDS_currentContext->sdlState;
		/* $(RTDS_HOME)/share/ccg/vxworks/bricks/RTDS_Proc_middle.c ends */
		/* ************************************************************* */

			/* Double switch state / signal */
			switch(RTDS_currentContext->sdlState)
				{
				case displaying:
					switch(RTDS_currentContext->currentMessage->messageNumber)
						{
						
						/* State displaying - signal tDisplay */
						case tDisplay:
							mode = NORMAL;
							Display( msgEnterCard, RTDS_currentContext);
							RTDS_SDL_STATE_SET(idle);
							break;
						
						} /* End of switch(RTDS_currentContext->currentMessage->messageNumber) */
					break;
				case doorOpen:
					switch(RTDS_currentContext->currentMessage->messageNumber)
						{
						
						/* State doorOpen - signal tDoor */
						case tDoor:
							RTDS_MSG_QUEUE_SEND_TO_ENV(close, 0, NULL);
							Display( msgEnterCard, RTDS_currentContext);
							mode=NORMAL;
							RTDS_SDL_STATE_SET(idle);
							break;
						
						} /* End of switch(RTDS_currentContext->currentMessage->messageNumber) */
					break;
				case adminMode:
					switch(RTDS_currentContext->currentMessage->messageNumber)
						{
						
						/* State adminMode - signal key */
						case key:
							lengthKey = RTDS_currentContext->currentMessage->dataLength;
							pKey = RTDS_currentContext->currentMessage->pData;
							if ( (*pKey) == (DELETE_USER_KEY) )
								{
								mode = DELETE_USER;
								Display(msgEnterCardToDelete, RTDS_currentContext);
								RTDS_SDL_STATE_SET(idle);
								} /* End of if ( (*pKey) == (DELETE_USER_KEY) ) */
							else if ( (*pKey) == (ADD_USER_KEY) )
								{
								mode = ADD_USER;
								Display(msgEnterNewCard, RTDS_currentContext);
								RTDS_SDL_STATE_SET(idle);
								} /* End of if ( (*pKey) == (ADD_USER_KEY) ) */
							else 
								{
								mode = NORMAL;
								goto lOpen;
								
								lOpen:
								
								
								_label1:
								Display(msgDoorOpen, RTDS_currentContext);
								RTDS_MSG_QUEUE_SEND_TO_ENV(open, 0, NULL);
								RTDS_SET_TIMER(tDoor, 1000);
								RTDS_SDL_STATE_SET(doorOpen);
								} /* End of  */
							break;
						
						} /* End of switch(RTDS_currentContext->currentMessage->messageNumber) */
					break;
				case idle:
					switch(RTDS_currentContext->currentMessage->messageNumber)
						{
						
						/* State idle - signal card */
						case card:
							lengthCardId = RTDS_currentContext->currentMessage->dataLength;
							pCardId = RTDS_currentContext->currentMessage->pData;
							Display(msgEnterCode, RTDS_currentContext);
							RTDS_SET_TIMER(tCode, 1000);
							pCodeId = malloc(CODE_SIZE);
							lengthCodeId = 0;
							RTDS_SDL_STATE_SET(waitCode);
							break;
						
						} /* End of switch(RTDS_currentContext->currentMessage->messageNumber) */
					break;
				case waitCentral:
					switch(RTDS_currentContext->currentMessage->messageNumber)
						{
						
						/* State waitCentral - signal Ok */
						case Ok:
							Display(msgOk, RTDS_currentContext);
							
							_label2:
							RTDS_SET_TIMER(tDisplay, 300);
							RTDS_SDL_STATE_SET(displaying);
							break;
						
						/* State waitCentral - signal Employee */
						case Employee:
							goto _label1;
							break;
						
						/* State waitCentral - signal Intruder */
						case Intruder:
							Display( msgInvalidCardOrCode, RTDS_currentContext);
							RTDS_SET_TIMER(tDisplay, 300);
							RTDS_SDL_STATE_SET(displaying);
							break;
						
						/* State waitCentral - signal Ko */
						case Ko:
							Display(msgKo, RTDS_currentContext);
							goto _label2;
							break;
						
						/* State waitCentral - signal Administrator */
						case Administrator:
							Display(msgAdmin, RTDS_currentContext);
							RTDS_SDL_STATE_SET(adminMode);
							break;
						
						} /* End of switch(RTDS_currentContext->currentMessage->messageNumber) */
					break;
				case waitCode:
					switch(RTDS_currentContext->currentMessage->messageNumber)
						{
						
						/* State waitCode - signal tCode */
						case tCode:
							Display(msgEnterCard, RTDS_currentContext);
							RTDS_SDL_STATE_SET(idle);
							break;
						
						/* State waitCode - signal key */
						case key:
							lengthKey = RTDS_currentContext->currentMessage->dataLength;
							pKey = RTDS_currentContext->currentMessage->pData;
							*(pCodeId+lengthCodeId) = *pKey;
							lengthCodeId++;
							free(pKey);
							if ( (lengthCodeId) == CODE_SIZE )
								{
								RTDS_RESET_TIMER(tCode);
								Display(msgPleaseWait, RTDS_currentContext);
								lenMsg = sizeof(tCardAndCode);
								pCardAndCode = (tCardAndCode *) malloc(lenMsg);
								pCardAndCode->cardLength = lengthCardId;
								pCardAndCode->cardId = pCardId;
								pCardAndCode->codeLength = lengthCodeId;
								pCardAndCode->codeId = pCodeId;
								if ( (mode) == (ADD_USER) )
									{
									RTDS_MSG_QUEUE_SEND_TO_NAME(AddUser, lenMsg, pCardAndCode, "pCentral");
									RTDS_SDL_STATE_SET(waitCentral);
									} /* End of if ( (mode) == (ADD_USER) ) */
								else if ( (mode) == (NORMAL) )
									{
									RTDS_MSG_QUEUE_SEND_TO_NAME(CardAndCode, lenMsg, pCardAndCode, "pCentral");
									RTDS_SDL_STATE_SET(waitCentral);
									} /* End of if ( (mode) == (NORMAL) ) */
								else if ( (mode) == (DELETE_USER) )
									{
									RTDS_MSG_QUEUE_SEND_TO_NAME(DeleteUser, lenMsg, pCardAndCode, "pCentral");
									RTDS_SDL_STATE_SET(waitCentral);
									} /* End of if ( (mode) == (DELETE_USER) ) */
								} /* End of if ( (lengthCodeId) == CODE_SIZE ) */
							else 
								{
								DisplayStar(lengthCodeId, RTDS_currentContext);
								RTDS_SDL_STATE_SET(waitCode);
								} /* End of  */
							break;
						
						} /* End of switch(RTDS_currentContext->currentMessage->messageNumber) */
					break;
				} /* End of switch(RTDS_currentContext->sdlState) */

			/* ************************************************************ */
			/* $(RTDS_HOME)/share/ccg/vxworks/bricks/RTDS_Proc_end.c begins */
			/* Copyright (C) 2002 PragmaDev */

			/* If message was not saved */
			if (RTDS_currentContext->currentMessage != NULL )
				{
				/* Free memory */
				RTDS_FREE(RTDS_currentContext->currentMessage);
				RTDS_currentContext->currentMessage = NULL;

				/* If SDL state has changed and messages have been saved: reorganise the save queue */
				if ( (RTDS_currentContext->sdlState != RTDS_sdlStatePrev) && (RTDS_writeSaveQueue != NULL) )
					{
					RTDS_MessageHeader	*message;
					/* Let's get to the end of the save queue */
					for (message=RTDS_writeSaveQueue ; message->next != NULL ; message = message->next);
					message->next = RTDS_readSaveQueue;
					RTDS_readSaveQueue = RTDS_writeSaveQueue;
					RTDS_writeSaveQueue = NULL;
					}
				} /* End of else if ( RTDS_currentContext->currentMessage != NULL ) */
            /* Since a transition has been executed; the sdl state is considered different to execute continuous signals. */
            RTDS_sdlStatePrev = 0;
			} /* End of if ( RTDS_currentContext->currentMessage != NULL ) */
		} /* End of for ( ; ; ) */

	/* Resources clean up */
	RTDS_PROCESS_KILL;
	}
	/* $(RTDS_HOME)/share/ccg/vxworks/bricks/RTDS_Proc_end.c ends */
	/* ********************************************************** */