/*******************************************************************************
 * Copyright (c) 2005, 2006 Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Vishnu K Naikawadi,Intel - Initial API and implementation
 *
 * $Id: EventProviderImpl.cpp,v 1.9 2006/02/10 18:44:11 koleary Exp $ 
 *******************************************************************************/ 

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#ifndef _WIN32
#include <strings.h>
#endif

using namespace std;

#include "tptp/agents/EventProviderImpl.h"



// eventsIID - the interface ID string of the events they want to hear about
// listenerIID - the value to use for the "context" of the event when sent
// replyDest - where to send the event notification
// replyContext - Context for the handler of the event at the destination
//
int EventProviderImpl::addEventListener(CmdBlock* cmd)
{
	tptp_listener_t* listener = 0;
	char replyCmd[BUFFER_LENGTH];

	int            sourceID;
	int            replyContext;
	int			   replyDest;
	char*          interfaceID = 0;
	char*          cmdName = 0;
	tptp_list_t*   paramList;
	char* listenToEventIID=NULL;
	int listenerID=0;
	tptp_node_t*  node=0;

	sourceID = cmd->getSourceID();
	replyContext = cmd->getContextID();
	replyDest = cmd->getDestID();
	interfaceID = cmd->getIID();
	cmdName = cmd->getCommandName();
	paramList = cmd->getParamList();

	if (0 != getStringParam( "interfaceID", paramList, &listenToEventIID ) )
	{	
		// No interfaceID event filter is ok.
		return -1;
	}

	if (0 != getIntegerParam( "listenerID", paramList, &listenerID ) )
	{	
		// No listenerID to use as conext value when reporting event is ok.
		return -1;
	}	

	tptp_listener_t* currListener = 0;
	for (node = eventListenerList.head; node != 0; node = node->next )
	{
		currListener = (tptp_listener_t*)node->data;
		if (currListener->listenerID == listenerID && sourceID == currListener->destID &&
				isEqualString(listenToEventIID, currListener->eventInterfaceID) == 0)
		{
			listener = currListener;
			break;
		}
	}

	if (listener == 0)
	{
		listener = (tptp_listener_t*)tptp_malloc( sizeof(tptp_listener_t) );
		if ( listener == 0 )
		{
			/* TODO: Report an error */
			return -1;
		}
		listener->destID = sourceID;
		listener->listenerID = listenerID;
		strcpy( listener->eventInterfaceID, listenToEventIID ); //TODO: Check if eventsIID exceeds MAX_PATH
		tptp_list_add(&eventListenerList, (void*)listener); //TODO: Check for error return
	}

	
	sprintf( replyCmd, "<Cmd src=\"%d\" dest=\"%d\" ctxt=\"%d\"> "
				   "<listenerAccepted iid=\"%s\">"
				   "</listenerAccepted></Cmd>",
				   getAgentID(), sourceID, replyContext,
				   EVENT_PROVIDER_IID);
	
	sendCommand(replyCmd);
	
	return 0;


}



int EventProviderImpl::removeEventListener(CmdBlock* cmd)
{
	tptp_listener_t* listener;
	char replyCmd[BUFFER_LENGTH];

	int            sourceID;
	int            replyContext;
	int			   replyDest;
	char*          interfaceID = 0;
	char*          cmdName = 0;
	tptp_list_t*   paramList;
	char* listenToEventIID=NULL;
	int listenerID=0;

	sourceID = cmd->getSourceID();
	replyContext = cmd->getContextID();
	replyDest = cmd->getDestID();
	interfaceID = cmd->getIID();
	cmdName = cmd->getCommandName();
	paramList = cmd->getParamList();

	tptp_node_t*  node;
	//agent_t*      agent;

	if (0 != getStringParam( "interfaceID", paramList, &listenToEventIID ) )
	{	
		// No interfaceID event filter is ok.
		return -1;
	}

	if (0 != getIntegerParam( "listenerID", paramList, &listenerID ) )
	{	
		// No listenerID to use as conext value when reporting event is ok.
		return -1;
	}

	for (node = eventListenerList.head; node != 0; node = node->next )
	{
		listener = (tptp_listener_t*)node->data;
		if (listener->listenerID == listenerID && sourceID == listener->destID &&
				isEqualString(listenToEventIID, listener->eventInterfaceID) == 0)
		{
			tptp_list_remove(&eventListenerList, listener);
			break;
		}
	}
	
	sprintf( replyCmd, "<Cmd src=\"%d\" dest=\"%d\" ctxt=\"%d\"> "
				   "<listenerRemoved iid=\"%s\">"
				   "</listenerRemoved></Cmd>",
				   getAgentID(), sourceID, replyContext,
				   EVENT_PROVIDER_IID);
	
	sendCommand(replyCmd);
	
	return 0;

}



void EventProviderImpl::sendEventNotifications(CmdBlock* cmd)
{
	tptp_node_t*     node;
	tptp_listener_t* listener;
	char eventCmd[BUFFER_LENGTH];
	char parmListCmd[BUFFER_LENGTH];
	tptp_list_t*   paramList;


	if (eventListenerList.count == 0)
	{
		return;
	}

	for (node = eventListenerList.head; node != 0; node = node->next )
	{
		listener = (tptp_listener_t*)node->data;
		
		//Send the event data to each listener
		if (isEqualString(cmd->getIID(), listener->eventInterfaceID))
		{
			paramList = cmd->getParamList();;
			string* parmStr = new string();
			tptp_node_t*  param_node;
			tptp_param_t* tmpParam;

			for (param_node = paramList->head; param_node != 0; param_node = param_node->next)
			{
				tmpParam = (tptp_param_t*)param_node->data;
				if ( !tmpParam ) continue;  //empty data field, skip this node				
				sprintf( parmListCmd, "<%s>%s</%s>", tmpParam->name, tmpParam->value, tmpParam->name);
				parmStr->append(parmListCmd);
			}			

			sprintf( eventCmd, "<Cmd src=\"%d\" dest=\"%d\" ctxt=\"%d\"> "
				   "<%s iid=\"%s\">%s"
				   "</%s></Cmd>",
				   getAgentID(), listener->destID, listener->listenerID,
				   cmd->getCommandName(), cmd->getIID(), parmStr->c_str(), cmd->getCommandName());
			delete (parmStr);

			sendCommand(eventCmd);
		}
	}
	return;
}


int EventProviderImpl::processEventProviderCommands(CmdBlock* cmd)
{

	int ret = -1;
	char*          cmdName = 0;

	//Handle basic agent commands
	BaseAgentImpl::processCommand(cmd);

	cmdName = cmd->getCommandName();

	if (isEqualString(cmdName, "addEventListener"))
	{			
		// Command: addEventListener
		// Expected parameters: CmdBlock
		addEventListener(cmd);
		ret = 0;
	}
	else if (isEqualString(cmdName, "removeEventListener"))
	{			
		// Command: removeEventListener
		// Expected parameters: CmdBlock
		removeEventListener(cmd);
		ret = 0;
	}

	return ret;
}



