/* ---------------------------------------------------------------------------
 * MessageHandlerQueue.c - v0.1                         (c) 2008 Micro-key bv
 * ---------------------------------------------------------------------------
 * Micro-key bv
 * Industrieweg 28, 9804 TG Noordhorn
 * Postbus 92, 9800 AB Zuidhorn
 * The Netherlands
 * Tel: +31 594 503020
 * Fax: +31 594 505825
 * Email: support@microkey.nl  
 * Web: www.microkey.nl
 * ---------------------------------------------------------------------------
 * Description: 
 * ---------------------------------------------------------------------------
 * Version(s):  0.1, Jan 30, 2008, FSc
 *                   Creation.
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * System include files
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Application include files
 * ---------------------------------------------------------------------------
 */
#include "MessageHandlerQueue.h"

#include "FreeRTOS.h"
#include "task.h"

/* ---------------------------------------------------------------------------
 * Local constant and macro definitions
 * ---------------------------------------------------------------------------
 */

typedef struct t_mhq_ENTITY
{
	UINT8                  messageId;
	t_bp_messagehandler    messageHandler;
	int                    ownHandle;
	struct t_mhq_ENTITY   *next;
	struct t_mhq_ENTITY   *previous; 
} t_mhq_entity;

typedef struct t_mhq_ADMIN
{
	struct t_mhq_ENTITY  *head;
	struct t_mhq_ENTITY  *tail;
} t_mhq_admin;

/* ---------------------------------------------------------------------------
 * Global variable definitions
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Local variable definitions
 * ---------------------------------------------------------------------------
 */

/* ---------------------------------------------------------------------------
 * Local function definitions
 * ---------------------------------------------------------------------------
 */
static t_mhq_entity *lookupMhqEntry(int handle, UINT8 messageId);


int mhqInit()
{
	t_mhq_admin *newAdmin = (t_mhq_admin *)pvPortMalloc( sizeof(t_mhq_admin) );
	
	newAdmin->head = NULL;
	
	return (int)newAdmin;
}

void mhqDeinit(int handle)
{
	t_mhq_entity *iterator = ((t_mhq_admin *)handle)->head;
	
	while (iterator != NULL)
	{
		t_mhq_entity *nextItem = iterator->next;
		vPortFree( iterator );
		iterator = nextItem;
	}
		
	vPortFree( (t_mhq_admin *)handle );
}

void mhqAdd(int handle, UINT8 messageId, t_bp_messagehandler messageHandler, int ownHandle)
{
	t_mhq_admin  *theAdmin = (t_mhq_admin *)handle;
	t_mhq_entity *newEntry = (t_mhq_entity  *)pvPortMalloc( sizeof(t_mhq_entity) );

	// fill entry
	newEntry->messageId  = messageId;
	newEntry->messageHandler = messageHandler;
	newEntry->ownHandle   = ownHandle;
	newEntry->next        = NULL;
	newEntry->previous    = NULL;
		
	taskENTER_CRITICAL();
	{
		// Add to linked list
		if (theAdmin->head != NULL)
		{
			theAdmin->tail->next = newEntry;
			newEntry->previous = theAdmin->tail;
			theAdmin->tail = newEntry;
		}
		else
		{
			theAdmin->head = newEntry;
			theAdmin->tail = newEntry;
		}
	}
	taskEXIT_CRITICAL();
}

void mhqRemove(int handle, UINT8 messageId, t_bp_messagehandler messageHandler)
{
	t_mhq_entity *entry = lookupMhqEntry(handle, messageId);
	t_mhq_admin *theAdmin = (t_mhq_admin *)handle;

	taskENTER_CRITICAL();
	{
		if (entry != NULL)
		{
			// rebuild linked list
			if (entry->next != NULL)
			{
				entry->next->previous = entry->previous;
			}
			else
			{
				theAdmin->tail = entry->previous;
			}
	
			if (entry->previous != NULL)
			{
				entry->previous->next = entry->next;
			}
			else
			{
				theAdmin->head = entry->next;
			}
			
			// remove entry
			vPortFree( entry );
		}
	}
	taskEXIT_CRITICAL();
}

RESULT mhqExecute(int handle, UINT8 messageId, t_bpmsg_message *message)
{
	t_mhq_entity *item = lookupMhqEntry(handle, messageId);
	
	if (item != NULL)
	{
		item->messageHandler( message, item->ownHandle );
		
		return OK;
	}
	else
	{
		return ERROR;
	}
}
 

t_mhq_entity *lookupMhqEntry(int handle, UINT8 messageId)
{
	t_mhq_admin *theAdmin = (t_mhq_admin *)handle;
	t_mhq_entity *result = NULL;
	t_mhq_entity *iterator;
	
	taskENTER_CRITICAL();
	{
		iterator = theAdmin->head;
		while ((result == NULL) && (iterator != NULL))
		{
			if (iterator->messageId == messageId)
			{
				result = iterator;
			}
			else
			{
				iterator = iterator->next;
			}
		}
	}
	taskEXIT_CRITICAL();
	
	return result;
}




