/*******************************************************************************
 * Copyright (c) 2005, 2006 Intel Corporation, IBM.
 * 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 (Based on the Java
 *                                API implementation by IBM)
 *
 * $Id: AgentController.cpp,v 1.18 2006/08/28 18:42:09 akaylor Exp $
 *
 *******************************************************************************/ 


#include "tptp/TPTPUtils.h"
//#include "TPTPCommon.h"
#include "tptp/client/ControlMessage.h"
#include "GetAgentCommand.h"
#include "tptp/client/Constants.h"
#include "tptp/client/TPTP_XMLHandler.h"
#include "tptp/client/CommandFragment.h"
#include "tptp/TPTPSupportTypes.h"
#include "tptp/NoLog.h"
#include "tptp/client/AgentController.h"
#include "ProcessImpl.h"
#include "ConnectionImpl.h"
#include "ConsoleDataProcessor.h"
#include "tptp/TPTPCommand.h"

#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <vector>

using namespace std;
using namespace TPTP::Client;

vector<Agent *> AgentController::agentList; 

AgentController::AgentController()
{
	_node = NULL;
	_consoleDataConnID = -1;
	_consoleDataProcessor = 0;
	
}


AgentController::AgentController(INode* node)
{
	_node = node;
	_consoleDataConnID = -1;
	_consoleDataProcessor = 0;
}

AgentController::~AgentController()
{
	delete(_connection);
}

void AgentController::destroy()
{
	delete(_connection);
}


/**
 * Retrieve the connection associated with this node object
 */
IConnection* AgentController::getConnection()
{
	return _connection;
}

void AgentController::setConnection(IConnection* conn)
{
	_connection = conn;
	addGenericListener();
}

void AgentController::disconnect()
{
	_connection->disconnect();
}

int AgentController::authenticateUser(User* user)
{
	int retVal = -1;

	ControlMessage* message = new ControlMessage();
	message->setMessageType(Constants::NEW_AC_MESSAGE);
	message->setMagicNumber(Constants::AC_MAGIC_NUMBER);
	message->setFlags(0);
	
	TPTPCommand* GetAgentCommand = new TPTPCommand();
	GetAgentCommand->setSourceID(_connection->getConnectionId());
	GetAgentCommand->setDestID(AGENT_MANAGER);
	GetAgentCommand->setContextID(_connection->getNextContextID());
	GetAgentCommand->setIID("org.eclipse.tptp.agentManager");
	GetAgentCommand->setCommandName("authenticateUser");
	GetAgentCommand->addStringParam("userName", user->getUserName());
	GetAgentCommand->addStringParam("password", user->getPassword());
	
	ACCommandHandler* acCommandHandler = new ACCommandHandler();
	

	try {
		_connection->sendMessage(GetAgentCommand, acCommandHandler);	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return -1;
	};

	if (acCommandHandler->checkResponseReceived() == 8)
	{
		TPTP_LOG_DEBUG_MSG("User Authentication Failed");
		return retVal;
	}
	else if (acCommandHandler->checkResponseReceived() == 7)
	{
		TPTP_LOG_DEBUG_MSG("User Authentication Successful");
		retVal = 0;
	}
	else if (acCommandHandler->checkResponseReceived() == 9)
	{
		TPTP_LOG_DEBUG_MSG("User Authentication UnSuccessful");
		delete(GetAgentCommand);
		delete(acCommandHandler);
		return retVal;
	}

	return retVal;
}

int AgentController::getAgent(Agent* agent, int flags)
{
	int agentID = -1;

	TPTPCommand* GetAgentCommand = new TPTPCommand();
	GetAgentCommand->setSourceID(_connection->getConnectionId());
	GetAgentCommand->setDestID(AGENT_MANAGER);
	GetAgentCommand->setContextID(_connection->getNextContextID());
	GetAgentCommand->setIID("org.eclipse.tptp.agentManager");
	GetAgentCommand->setCommandName("getAgent");
	GetAgentCommand->addStringParam("agentName", agent->getAgentName());
	GetAgentCommand->addIntegerParam("flags", flags);
	
	ACCommandHandler* acCommandHandler = new ACCommandHandler();
	

	try {
		_connection->sendMessage(GetAgentCommand, acCommandHandler);	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return -1;
	};


	if (acCommandHandler->checkResponseReceived() == 6)
	{
		TPTP_LOG_DEBUG_MSG("Agent is Unavailable");
	}
	else if (acCommandHandler->checkResponseReceived() == 9)
	{
		delete(GetAgentCommand);
		delete(acCommandHandler);
		return agentID;
	}
	else if (acCommandHandler->checkResponseReceived() == 1)
	{
		int            ret = -1;
		int            sourceID;
		int            contextID;
		char*          interfaceName;
		char*          cmdName;
		tptp_list_t*   paramList;
		ret = parseCommand(acCommandHandler->getResponseCommand()->getCommand(),&sourceID, &contextID, &interfaceName, &cmdName, &paramList );
		char* agentRef = 0;
		ret = getStringParam("agentID",paramList,&agentRef);
	
		agentID = atoi(agentRef);
		if(agentID == -1)
		{
			//write the error , clean up
			tptp_free(interfaceName);
			tptp_free(cmdName);
			delete(GetAgentCommand);
			delete(acCommandHandler);
			return agentID;
		}
		agent->setACProxy(this);
		agent->setAgentID(agentID);
		AgentController::agentList.push_back(agent);
	}

	delete(GetAgentCommand);
	delete(acCommandHandler);
	
	return agentID;
}


int AgentController::getAgentByProcessID(Agent* agent, int pid, int flags)
{
	int agentID = -1;

	TPTPCommand* GetAgentByProcessIDCommand = new TPTPCommand();
	GetAgentByProcessIDCommand->setSourceID(_connection->getConnectionId());
	GetAgentByProcessIDCommand->setDestID(AGENT_MANAGER);
	GetAgentByProcessIDCommand->setContextID(_connection->getNextContextID());
	GetAgentByProcessIDCommand->setIID("org.eclipse.tptp.agentManager");
	GetAgentByProcessIDCommand->setCommandName("getAgentByProcessID");
	GetAgentByProcessIDCommand->addIntegerParam("processID", pid);
	GetAgentByProcessIDCommand->addIntegerParam("flags", flags);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(GetAgentByProcessIDCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return -1;
	};


	if (acCommandHandler->checkResponseReceived() == 6)
	{
		TPTP_LOG_DEBUG_MSG("Agent is Unavailable");
	}
	else if(acCommandHandler->checkResponseReceived() == 9)
	{
		delete(GetAgentByProcessIDCommand);
		delete(acCommandHandler);
		return agentID;
	}
	else if (acCommandHandler->checkResponseReceived() == 1)
	{
		int            ret = -1;
		int            sourceID;
		int            contextID;
		char*          interfaceName;
		char*          cmdName;
		tptp_list_t*   paramList;
		ret = parseCommand(acCommandHandler->getResponseCommand()->getCommand(),&sourceID, &contextID, &interfaceName, &cmdName, &paramList );
		char* agentRef = 0;
		ret = getStringParam("agentID",paramList,&agentRef);
	
		agentID = atoi(agentRef);
		if(agentID == -1)
		{
			//write the error , clean up
			tptp_free(interfaceName);
			tptp_free(cmdName);
			delete(GetAgentByProcessIDCommand);
			delete(acCommandHandler);
			return agentID;
		}
		agent->setACProxy(this);
		agent->setAgentID(agentID);
		AgentController::agentList.push_back(agent);
	}

	delete(GetAgentByProcessIDCommand);
	delete(acCommandHandler);

	return agentID;
}


int AgentController::getAgentByToken(Agent* agent, int token, int flags)
{
	int agentID = -1;

	TPTPCommand* GetAgentByTokenCommand = new TPTPCommand();
	GetAgentByTokenCommand->setSourceID(_connection->getConnectionId());
	GetAgentByTokenCommand->setDestID(AGENT_MANAGER);
	GetAgentByTokenCommand->setContextID(_connection->getNextContextID());
	GetAgentByTokenCommand->setIID("org.eclipse.tptp.agentManager");
	GetAgentByTokenCommand->setCommandName("getAgentByToken");
	GetAgentByTokenCommand->addIntegerParam("token", token);
	GetAgentByTokenCommand->addIntegerParam("flags", flags);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(GetAgentByTokenCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	
	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return -1;
	};

	if (acCommandHandler->checkResponseReceived() == 6)
	{
		TPTP_LOG_DEBUG_MSG("Agent is Unavailable");
	}
	else if(acCommandHandler->checkResponseReceived() == 9)
	{
		delete(GetAgentByTokenCommand);
		delete(acCommandHandler);
		return agentID;
	}
	else if (acCommandHandler->checkResponseReceived() == 1)
	{
		int            ret = -1;
		int            sourceID;
		int            contextID;
		char*          interfaceName;
		char*          cmdName;
		tptp_list_t*   paramList;
		ret = parseCommand(acCommandHandler->getResponseCommand()->getCommand(),&sourceID, &contextID, &interfaceName, &cmdName, &paramList );
		char* agentRef = 0;
		ret = getStringParam("agentID",paramList,&agentRef);
	
		agentID = atoi(agentRef);
		if(agentID == -1)
		{
			//write the error , clean up
			tptp_free(interfaceName);
			tptp_free(cmdName);
			delete(GetAgentByTokenCommand);
			delete(acCommandHandler);
			return agentID;
		}
		agent->setACProxy(this);
		agent->setAgentID(agentID);
		AgentController::agentList.push_back(agent);
	}

	delete(GetAgentByTokenCommand);
	delete(acCommandHandler);

	return agentID;
}


int AgentController::getAgentByID(Agent* agent, int agentID, int flags)
{
	int retAgentID = -1;

	TPTPCommand* GetAgentByIDCommand = new TPTPCommand();
	GetAgentByIDCommand->setSourceID(_connection->getConnectionId());
	GetAgentByIDCommand->setDestID(AGENT_MANAGER);
	GetAgentByIDCommand->setContextID(_connection->getNextContextID());
	GetAgentByIDCommand->setIID("org.eclipse.tptp.agentManager");
	GetAgentByIDCommand->setCommandName("getAgentByID");
	GetAgentByIDCommand->addIntegerParam("agentID", agentID);
	GetAgentByIDCommand->addIntegerParam("flags", flags);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(GetAgentByIDCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	
	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return -1;
	};

	if (acCommandHandler->checkResponseReceived() == 6)
	{
		TPTP_LOG_DEBUG_MSG("Agent is Unavailable");
	}
	else if(acCommandHandler->checkResponseReceived() == 9)
	{
		delete(GetAgentByIDCommand);
		delete(acCommandHandler);
		return agentID;
	}
	else if (acCommandHandler->checkResponseReceived() == 1)
	{
		int            ret = -1;
		int            sourceID;
		int            contextID;
		char*          interfaceName;
		char*          cmdName;
		tptp_list_t*   paramList;
		ret = parseCommand(acCommandHandler->getResponseCommand()->getCommand(),&sourceID, &contextID, &interfaceName, &cmdName, &paramList );
		char* agentRef = 0;
		ret = getStringParam("agentID",paramList,&agentRef);
	
		agentID = atoi(agentRef);
		if(agentID == -1)
		{
			//write the error , clean up
			tptp_free(interfaceName);
			tptp_free(cmdName);
			delete(GetAgentByIDCommand);
			delete(acCommandHandler);
			return agentID;
		}
		agent->setACProxy(this);
		agent->setAgentID(agentID);
		AgentController::agentList.push_back(agent);
	}

	delete(GetAgentByIDCommand);
	delete(acCommandHandler);

	return retAgentID;
}


/* TPTP CLIENT API
 * Clients should call this method to get the Agent Metadata XML string
 * Takes the agent name as parameter.
 */
char* AgentController::getAgentMetaData(char* agentName)
{
	char* agentMetadata = 0;

	TPTPCommand* GetAgentMetaDataCommand = new TPTPCommand();
	GetAgentMetaDataCommand->setSourceID(_connection->getConnectionId());
	GetAgentMetaDataCommand->setDestID(AGENT_MANAGER);
	GetAgentMetaDataCommand->setContextID(_connection->getNextContextID());
	GetAgentMetaDataCommand->setIID("org.eclipse.tptp.agentManager");
	GetAgentMetaDataCommand->setCommandName("getAgentMetadata");
	GetAgentMetaDataCommand->addStringParam("agentName", agentName);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(GetAgentMetaDataCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return 0;
	};
	if(acCommandHandler->checkResponseReceived() == 9)
	{
		delete(GetAgentMetaDataCommand);
		delete(acCommandHandler);
		return agentMetadata;
	}
	if(acCommandHandler->checkResponseReceived() == 5)
	{
		int            ret = -1;
		int            sourceID;
		int            contextID;
		char*          interfaceName;
		char*          cmdName;
		tptp_list_t*   paramList;

		ret = parseCommand(acCommandHandler->getResponseCommand()->getCommand(), &sourceID, &contextID, &interfaceName, &cmdName, &paramList );
		getStringParam("metadata", paramList, &agentMetadata);

		// Free space allocated by parseCommand()
		tptp_free(interfaceName);
		tptp_free(cmdName);
		tptp_list_clear(paramList);
		tptp_free(paramList);
	}
	delete(GetAgentMetaDataCommand);
	delete(acCommandHandler);
	
	return agentMetadata;
}

/* TPTP CLIENT API
 * Clients should call this method to get the list of running agents
 * returns the array of agent names
 */
std::vector<Agent*>* AgentController::queryRunningAgents(int processID, char* interfaceName)
{
	char* agentInfoList = 0;
	std::vector<Agent*>* agentVector = new std::vector<Agent*>();

	TPTPCommand* QueryRunningAgentsCommand = new TPTPCommand();
	QueryRunningAgentsCommand->setSourceID(_connection->getConnectionId());
	QueryRunningAgentsCommand->setDestID(AGENT_MANAGER);
	QueryRunningAgentsCommand->setContextID(_connection->getNextContextID());
	QueryRunningAgentsCommand->setIID("org.eclipse.tptp.agentManager");
	QueryRunningAgentsCommand->setCommandName("queryRunningAgents");
	QueryRunningAgentsCommand->addIntegerParam("processID", processID);
	QueryRunningAgentsCommand->addStringParam("interfaces", interfaceName);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(QueryRunningAgentsCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return agentVector;
	};
	if(acCommandHandler->checkResponseReceived() == 9)
	{
		delete(QueryRunningAgentsCommand);
		delete(acCommandHandler);
		return agentVector;
	}
	if(acCommandHandler->checkResponseReceived() == 3)
	{
		int            ret = -1;
		int            sourceID;
		int            contextID;
		char*          interfaceName;
		char*          cmdName;
		tptp_list_t*   paramList;
		tptp_list_t*   agentInfo;

		ret = parseCommand(acCommandHandler->getResponseCommand()->getCommand(), &sourceID, &contextID, &interfaceName, &cmdName, &paramList );
		getStringParam("agentInfoList", paramList, &agentInfoList);

		if (agentInfoList == 0) return agentVector;

		//Parse the Agent Info List
		getXMLElements(agentInfoList, &agentInfo);

		// Loop through the list of parameters, find the agent name, token and pid	
		tptp_node_t*  node;
		tptp_param_t* tmpParam;
		int agentNum = 0;
		
		for (node = agentInfo->head; node != 0;)
		{
			tmpParam = (tptp_param_t*)node->data;
			if ( !tmpParam ) continue;  //empty data field, skip this node

			if ( isEqualString(tmpParam->name, "agentInfo"))
			{
				node = node->next;
				continue;
			}

			char agentName[1024];
			int agentToken = 0;
			PID agentPID = 0;
			Agent* agent = 0;

			for(int i=0; (i<3 && node != 0); i++)
			{
				tmpParam = (tptp_param_t*)node->data;
				if (!tmpParam) continue;

				if ( isEqualString(tmpParam->name, "name") )
				{					
					strcpy(agentName, tmpParam->value);				
				}
				else if ( isEqualString(tmpParam->name, "token") )
				{
					agentToken = atoi(tmpParam->value);
				}
				else if ( isEqualString(tmpParam->name, "pid") )
				{
					agentPID = atol(tmpParam->value);
				}

				node = node->next;
			}

			if (agentName)
			{
				agent = new Agent(agentName);
				agent->setAgentTokenID(agentToken);
				agent->setAgentProcessID(agentPID);
				agentVector->push_back(agent);
				agentNum++;
			}
		}

		// Free space allocated by parseCommand()
		if(interfaceName) tptp_free(interfaceName);
		if(cmdName) tptp_free(cmdName);
		if (paramList)
		{
			tptp_list_clear(paramList);
			tptp_free(paramList);
		}
	}

	delete(QueryRunningAgentsCommand);
	delete(acCommandHandler);

	return agentVector;
}

/* TPTP CLIENT API
 * Clients should call this method to get the list of deployed agents
 * returns the array of agent names
 */
std::vector<char*>* AgentController::queryDeployedAgents(char* interfaceName)
{
	std::vector<char*>* nameList = new std::vector<char*>();

	TPTPCommand* QueryDeployedAgentsCommand = new TPTPCommand();
	QueryDeployedAgentsCommand->setSourceID(_connection->getConnectionId());
	QueryDeployedAgentsCommand->setDestID(AGENT_MANAGER);
	QueryDeployedAgentsCommand->setContextID(_connection->getNextContextID());
	QueryDeployedAgentsCommand->setIID("org.eclipse.tptp.agentManager");
	QueryDeployedAgentsCommand->setCommandName("queryAvailableAgents");
	QueryDeployedAgentsCommand->addStringParam("interfaces", interfaceName);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(QueryDeployedAgentsCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	int rc = tptp_waitSemaphore(acCommandHandler->getResponseReceivedSem());
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("Error - wait for command response failed.");
		return nameList;
	};
	if(acCommandHandler->checkResponseReceived() == 9)
	{
		delete(QueryDeployedAgentsCommand);
		delete(acCommandHandler);
		return nameList;
	}
	if(acCommandHandler->checkResponseReceived() == 2)
	{
		int            ret = -1;
		int            sourceID;
		int            contextID;
		char*          interfaceName;
		char*          cmdName;
		tptp_list_t*   paramList;
		char* agentNameList = 0;

		ret = parseCommand(acCommandHandler->getResponseCommand()->getCommand(), &sourceID, &contextID, &interfaceName, &cmdName, &paramList );

		getStringParam("agentNames", paramList, &agentNameList);

		// Split the Agent Names and return as an Array	
		string agentName;
		string agentNames(agentNameList);
		stringstream agentNameStream(agentNames);

		while(agentNameStream >> agentName)
		{
			char* agentNameString = 0;
			if (agentName.c_str())
			{
				agentNameString = (char*)malloc(strlen((char*)(agentName.c_str())));
				strcpy(agentNameString, agentName.c_str());
				nameList->push_back(agentNameString);
			}			
		}

		// Free space allocated by parseCommand()
		if(interfaceName) tptp_free(interfaceName);
		if(cmdName) tptp_free(cmdName);
		if (paramList)
		{
			tptp_list_clear(paramList);
			tptp_free(paramList);
		}
		if(agentNameList) tptp_free(agentNameList);
	}

	delete(QueryDeployedAgentsCommand);
	delete(acCommandHandler);

	return nameList;
}


long AgentController::addEventListener(char* interfaceid,  ICommandHandler* listener)
{
	long listenerid = this->_connection->getNextContextID();

	TPTPCommand* AddEventListenerCommand = new TPTPCommand();
	AddEventListenerCommand->setSourceID(_connection->getConnectionId());
	AddEventListenerCommand->setDestID(AGENT_MANAGER);
	AddEventListenerCommand->setContextID(_connection->getNextContextID());
	AddEventListenerCommand->setIID("org.eclipse.tptp.agentManager");
	AddEventListenerCommand->setCommandName("addEventListener");
	AddEventListenerCommand->addStringParam("interfaceID", interfaceid);
	AddEventListenerCommand->addIntegerParam("listenerID", listenerid);

	((ConnectionImpl*)(this->_connection))->addContext(listenerid, listener);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(AddEventListenerCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	
	//while(acCommandHandler->checkResponseReceived() != 7)
	//{
	//	Sleep(1000);
	//}

	delete(acCommandHandler);
	return listenerid;
}



void AgentController::removeEventListener(char* interfaceid, long listenerid)
{
	TPTPCommand* RemoveEventListenerCommand = new TPTPCommand();
	RemoveEventListenerCommand->setSourceID(_connection->getConnectionId());
	RemoveEventListenerCommand->setDestID(AGENT_MANAGER);
	RemoveEventListenerCommand->setContextID(_connection->getNextContextID());
	RemoveEventListenerCommand->setIID("org.eclipse.tptp.agentManager");
	RemoveEventListenerCommand->setCommandName("addEventListener");
	RemoveEventListenerCommand->addStringParam("interfaceID", interfaceid);
	RemoveEventListenerCommand->addIntegerParam("listenerID", listenerid);

	ACCommandHandler* acCommandHandler = new ACCommandHandler();

	try {
		_connection->sendMessage(RemoveEventListenerCommand, acCommandHandler);
	
	}
	catch(exception e) 
	{
		// Should probably handle this one
		//cout<<"Exception in getAgent():"<<e<<endl;
	}

	
	//while(acCommandHandler->checkResponseReceived() != 8)
	//{
	//	Sleep(1000);
	//}

	delete(acCommandHandler);
	return;
}




void AgentController::sendCommand(char* cmd, int destID, ICommandHandler* handler)
{
	ACCommandHandler* acCommandHandler = NULL;

	ControlMessage* message = new ControlMessage();
	message->setMessageType(Constants::NEW_AC_MESSAGE);
	message->setMagicNumber(Constants::AC_MAGIC_NUMBER);
	message->setFlags(0);
	CommandFragment* cmdFrag = new CommandFragment();
	cmdFrag->setDestination(destID);
	cmdFrag->setSource(_connection->getConnectionId());
	cmdFrag->setContext(_connection->getNextContextID());
	cmdFrag->setCommandPart(cmd);
	cmdFrag->buildCommand();
	message->appendCommand(cmdFrag);	

	if (handler == NULL)
	{
		acCommandHandler = new ACCommandHandler();
		_connection->sendMessage(message, acCommandHandler);
	}
	else
	{
		_connection->sendMessage(message, handler);
	}

	delete(cmdFrag);
	delete(acCommandHandler);
	delete(message);
}


void AgentController::sendCommand(TPTPCommand* tptpCmd, ICommandHandler* handler)
{
	ACCommandHandler* acCommandHandler = NULL;

	if (handler == NULL)
	{
		acCommandHandler = new ACCommandHandler();
		_connection->sendMessage(tptpCmd, acCommandHandler);
	}
	else
	{
		_connection->sendMessage(tptpCmd, handler);
	}

	if (acCommandHandler != NULL)
	{
		delete(acCommandHandler);
	}
}


int AgentController::createDataConnection(int direction)
{
	return _connection->createDataConnection(direction, CONNECT_DATA);
}

/*
 * Destroy Data Connection
 */
int AgentController::destroyDataConnection(int dataConnID)
{
	return _connection->destroyDataConnection(dataConnID);
}


/*
 * Create Console Data Connection
 */
int AgentController::getConsoleDataConnection()
{
	//if (_consoleDataConnID == -1)
	//{
		_consoleDataConnID = _connection->createDataConnection(3, CONNECT_CONSOLE);
		//if (_consoleDataProcessor == 0)
		//{
		//	_consoleDataProcessor = new ConsoleDataProcessor();
		//}
		//addDataListener(_consoleDataConnID, _consoleDataProcessor);
	//}
	return _consoleDataConnID;
}


/*
 * Get the Console Data Processor
 */
IDataProcessor* AgentController::getConsoleDataProcessor()
{
	//return _consoleDataProcessor;
	return (new ConsoleDataProcessor());
}


int AgentController::addDataListener(int dataConnID, IDataProcessor* dataProcessor)
{
	//int dataConnID = createDataConnection();
	this->_connection->addDataListener(dataConnID, dataProcessor);
	return dataConnID;
}


int AgentController::removeDataListener(int dataConnID, IDataProcessor* dataProcessor)
{
	return this->_connection->removeDataListener(dataConnID, dataProcessor);
}


int AgentController::sendData(int dataConnectionID, char buffer[], int bufferLength)
{
	int returnCode = _connection->sendData(dataConnectionID, buffer, bufferLength);

	return returnCode;
}


int AgentController::sendConsoleData(char buffer[], int bufferLength)
{
	//add the dime header

	int returnCode = sendData(this->_consoleDataConnID, buffer, bufferLength);

	return returnCode;
}

//Add a generic listener for capturing non-context command responses
void AgentController::addGenericListener()
{
	ACCommandHandler* acCommandHandler = new ACCommandHandler();
    ((ConnectionImpl *)_connection)->getContextMapper()->addContext(-1, acCommandHandler);

}

IProcess* AgentController::createNewProcess()
{
	IProcess* NewProcess = new ProcessImpl(this);
	return NewProcess;
}

void AgentController::deleteProcess(IProcess* process)
{
	delete((ProcessImpl*)process);
}


ACCommandHandler::ACCommandHandler()
{
	this->agentID = -1;
	this->responseReceived = -1;
	responseCommand = NULL;
	int rc = tptp_initializeSemaphore(&responseReceivedSem);
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("BaseAgent registerAgent: Error - Exiting, failed to create synch event for registerAgentConnected.");		
	};
}

ACCommandHandler::~ACCommandHandler()
{
	if (responseCommand)
	{
		delete(responseCommand);
	}
	tptp_deleteSemaphore(&responseReceivedSem);
}

CommandElement* ACCommandHandler::getResponseCommand()
{
	return this->responseCommand;
}

void ACCommandHandler::incomingCommand(INode* node, CommandElement* command)
{
	TPTP_LOG_DEBUG_MSG("AC Command Handler called");

	TPTP_LOG_DEBUG_MSG1("Response for getAgent(): %s", command->getCommand());

	//cout<<"The response command - "<<command->getCommand()<<endl;

	responseCommand = new CommandFragment();
	responseCommand->setContext(command->getContext());
	responseCommand->setSource(command->getSource());
	responseCommand->setDestination(command->getDestination());
	responseCommand->setCommand(command->getCommand());

	int            ret = -1;
	int            sourceID;
	int            contextID;
	char*          interfaceName=0;
	char*          cmdName=0;
	tptp_list_t*   paramList=0;
		
	ret = parseCommand(command->getCommand(), &sourceID, &contextID, &interfaceName, &cmdName, &paramList );

	if (isEqualString(cmdName, "agentReference"))
	{
		responseReceived = 1;
	}
	if (isEqualString(cmdName, "availableAgents"))
	{
		responseReceived = 2;
	}
	if (isEqualString(cmdName, "runningAgents"))
	{
		responseReceived = 3;
	}
	if (isEqualString(cmdName, "controlGranted"))
	{
		responseReceived = 4;
	}
	if (isEqualString(cmdName, "agentMetadata"))
	{
		responseReceived = 5;
	}
	if (isEqualString(cmdName, "agentUnavailable"))
	{
		responseReceived = 6;
	}
	if (isEqualString(cmdName, "userAuthenticated"))
	{
		responseReceived = 7;
	}
	if (isEqualString(cmdName, "authenticationFailed"))
	{
		responseReceived = 8;
	}
	if (isEqualString(cmdName, "TPTP_Error"))
	{
		responseReceived = 9;
		char *errStr=NULL;
		getStringParam("ErrInfo", paramList, &errStr);
		//TODO: Use the logging service here
		//cout<<"Received Error Response:"<<errStr<<endl;
		if (errStr)tptp_free(errStr);
	}
	if (isEqualString(cmdName, "agentProcessExited"))
	{
		responseReceived = 10;
		int agentID=-1;
		char* agentRef = 0;
		ret = getStringParam("agentID",paramList,&agentRef);
		//cout<<"Agent Manager Event Recvd:"<<cmdName<<": Agent ID = "<<agentRef<<endl;
		if (agentRef)
		{
			agentID = atoi(agentRef);
		}
		if(agentID == -1)
		{
			//Log error message
		}
		//TODO: Use the logging service here
		else
		{
			for(int i = 0; i < AgentController::agentList.size();i++)
			{
				if(((Agent *)AgentController::agentList[i])->getAgentID() == agentID)
				{
					//TODO:throw an exception, the exception should be handled and the Agent resources released and flags reset
					//((Agent *)AgentController::agentList[i])->releaseAgent();
					//throw agentID;
				}
			}
		}
		if (agentRef)tptp_free(agentRef);
	}
	int rc = tptp_postSemaphore(&responseReceivedSem);
	if (rc != 0)
	{
		TPTP_LOG_ERROR_MSG("BaseAgent processCommand: Error - failed to post event for registerAgentCompleted.");
	}

	// Free space allocated by parseCommand()
	if (ret != -1)
	{
		if (interfaceName)tptp_free(interfaceName);
		if(cmdName)tptp_free(cmdName);
		if(paramList)
		{
			tptp_list_clear(paramList);
			tptp_free(paramList);
		}
	}

}


int ACCommandHandler::checkResponseReceived()
{
	return responseReceived;
}

int ACCommandHandler::getAgentID()
{
	return agentID;
}

Semaphore_t* ACCommandHandler::getResponseReceivedSem()
{
	return &responseReceivedSem;
}







