/*******************************************************************************
 * Copyright (c) 2005 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: NodeImpl.cpp,v 1.8 2005/09/12 18:01:39 akaylor Exp $
 *
 *******************************************************************************/ 



#include "NodeImpl.h"
#include "ConnectionImpl.h"
#include "tptp/TPTPCommon.h"
#include "tptp/NoLog.h"


#define CONNECT_TIMEOUT 5

using namespace TPTP::Client;


NodeImpl::NodeImpl()
{
	//_connection = NULL;
	//_ac = NULL;
	_name = NULL;
}

NodeImpl::NodeImpl(char* hostName)
{
	_name = hostName;
	//_connection = NULL;
	//_ac = NULL;
}


NodeImpl::~NodeImpl()
{
	_acList.clear();
}



/**
 * Is this controller connected to this node
 */
bool NodeImpl::isConnected(int port)
{
	AgentController* acProxy = getAC(port);

	if (acProxy != NULL)
	{
		return true;
	}

	return false;

}

/**
 * Attempt to connect to this node.
 */
AgentController* NodeImpl::connect(int port)
{
	IConnection* connection = 0;
	AgentController* acProxy = 0;
	int timeOut = CONNECT_TIMEOUT; // 10 seconds
	int tryCount = 1;

	if(connection == NULL) {
		try 
		{
			connection = new ConnectionImpl();
			int rc = 0;
			do
			{
				rc = connection->connect(this, port);
				tryCount++;				
			}
			while (rc < 0 && tryCount < timeOut);
			if (rc < 0)
			{
				TPTP_LOG_ERROR_MSG3("Error: unable to connect to the Agent Controller on %s at port# %d. Error Code - %d", _name, port, rc);
			}
			else
			{
				while (connection->getConnectionId() == -1 && rc == 0)
				{
					SLEEP(1000);				
				}
				if (rc == 0)
				{
					acProxy = getAC(port);
					acProxy->setConnection(connection);
				}
			}
		}
		catch(exception e) {
			connection = NULL;
			//throw e;
		}
	}

	return acProxy;

}


/**
 * Attempt to connect to this node.
 */
AgentController* NodeImpl::connect(ConnectionInfo* connInfo)
{
	IConnection* connection = 0;
	AgentController* acProxy = 0;
	int timeOut = CONNECT_TIMEOUT; // 10 seconds
	int tryCount = 1;

	if(connection == NULL) {
		try 
		{
			connection = new ConnectionImpl();
			int rc = 0;
			do
			{
				rc = connection->connect(this, connInfo);
				tryCount++;				
			}
			while (rc < 0 && tryCount < timeOut);
			if (rc < 0)
			{
				TPTP_LOG_ERROR_MSG3("Error: unable to connect to the Agent Controller on %s at port# %d. Error Code - %d", _name, connInfo->getPortNum(), rc);
			}
			else
			{
				while (connection->getConnectionId() == -1 && rc == 0)
				{
					SLEEP(1000);				
				}
				if (rc == 0)
				{
					acProxy = getAC(connInfo->getPortNum());
					acProxy->setConnection(connection);
				}
			}
		}
		catch(exception e) {
			connection = NULL;
			//throw e;
		}
	}

	return acProxy;

}


/**
 * Attempt to connect to this node.
 */
AgentController* NodeImpl::connect(ConnectionInfo* connInfo, User* user)
{	
	AgentController* acProxy = this->connect(connInfo);

	int retVal = acProxy->authenticateUser(user);
	if (retVal == 0)
	{
		return acProxy;
	}
	else
	{
		delete (acProxy);
		return NULL;
	}
}



void NodeImpl::disconnect(int port)
{
	getAC(port)->disconnect();
}


/**
 * Retrieve the InetAddress for this Node.
 */
char* NodeImpl::getInetAddress()
{
	return _addr;
}


/**
 * Retrieve the host name for this Node.
 */
char* NodeImpl::getName()
{
	return _name;
}

/**
 * Retrieve the host name for this Node.
 */
void NodeImpl::setName(char* name)
{
	_name = name;
}



AgentController* NodeImpl::getAC(int port)
{
	AgentController* ac;
	std::map<int, AgentController*>::iterator  mapIterator = _acList.find(port);
	if (mapIterator == _acList.end())
	{
		// not found, add the given pair to the table		
		ac = new AgentController();
		_acList.insert(std::map<int, AgentController*>::value_type(port, ac));
	}
	else
	{
		ac = (AgentController*)mapIterator->second;
	}

	return ac;
}

