//
//noderef.c
//
//Functions relevant to the maintainence of node reference.
//
//
//-UserX 2001/11/05

#include <string.h>
#include "misc/compat.h"
#include "base/logger.h"
#include "base/mem.h"
#include "base/array.h"
#include "base/str.h"
#include "net/noderef.h"
#include "net/protocol.h"
#include "net/protocfg.h"
//#include "random.h"
#include "base/itag.h"

char defaulttransport[] = "tcp";

NodeRef noderefblank = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, PROTOCOL_DEFAULTPORT, 0};
ENodeRef enoderefblank = {NULL, 0, 0};
//{"", PROTOCOL_DEFAULTPORT, 0,  0, 0};


StringIntPair noderefspecials[] = {
		{"entry", NRS_ENTRY},
		{"exit", NRS_EXIT},
		{NULL, -1}
	};


ENodeRefArrayHandle *NRA = NULL;

NodeRefArrayHandle *LNRA = NULL;




//todo: break the extra uncommon stuff into a seperate init function
void noderefInit(NodeRef *nr, char *hostname, char *protocol, char *transport, char *publickey, char *privatekey, char *special, char *netname, char *version, int portnum) {
	LOGDEBUG(stringJoin("noderefInit:", ptrToString(nr)));
	nr->HostName = stringReplace(nr->HostName, hostname);
	nr->Protocol = stringReplace(nr->Protocol, protocol);
	nr->Transport = stringReplace(nr->Transport, transport);
	nr->PublicKey = stringReplace(nr->PublicKey, publickey);
	nr->PrivateKey = stringReplace(nr->PrivateKey, privatekey);
	nr->Special = stringReplace(nr->Special, special);
	nr->netname = stringReplace(nr->netname, netname);
	nr->version = stringReplace(nr->version, version);
	nr->PortNum = portnum;
}

void noderefMakeAt(NodeRef *nr) {
	LOGDEBUG(stringJoin("noderefMakeAt:", ptrToString(nr)));
	if(nr == NULL) {
		return;
	}
	nr->iTag = itagGet();
}

NodeRef *noderefMake(void) {
	NodeRef *nr = memAlloc(sizeof(NodeRef), "NodeRef", NULL);//ximalloc(sizeof(NodeRef));
	LOGDEBUG(stringJoin("noderefMake:", ptrToString(nr)));
	noderefMakeAt(nr);
	return nr;
}

//creates a copy of an existing NodeRef
NodeRef *noderefCopy(NodeRef *nr) {
	NodeRef *nnr;
	LOGDEBUG(stringJoin("noderefCopy:", ptrToString(nr)));
	if(nr == NULL) {
		return NULL;
	}
	nnr = memAlloc(sizeof(NodeRef), "NodeRef", NULL);//ximalloc(sizeof(NodeRef));
	LOGDEBUG(stringJoin("- copy:", ptrToString(nnr)));
	nnr->HostName = stringCopy(nr->HostName);
	nnr->Protocol = stringCopy(nr->Protocol);
	nnr->Transport = stringCopy(nr->Transport);
	nnr->PublicKey = stringCopy(nr->PublicKey);
	nnr->PrivateKey = stringCopy(nr->PrivateKey);
	nnr->Special = stringCopy(nr->Special);
	nnr->netname = stringCopy(nr->netname);
	nnr->version = stringCopy(nr->version);
	nnr->PortNum = nr->PortNum;
	nnr->iTag = nr->iTag;
	return nnr;
}

void noderefDelete(NodeRef *nr) {
	if(nr == NULL) {
		return;
	}
	stringFree(nr->HostName);
	stringFree(nr->Protocol);
	stringFree(nr->Transport);
	stringFree(nr->PublicKey);
	stringFree(nr->PrivateKey);
	stringFree(nr->Special);
	stringFree(nr->netname);
	stringFree(nr->version);
}

void noderefFree(NodeRef *nr) {
	LOGDEBUG(stringJoin("noderefFree:", ptrToString(nr)));
	if(nr == NULL) {
		return;
	}
	noderefDelete(nr);
	memFree(nr);
}

void enoderefInit(ENodeRef *nr) {
	//nodeRefInit((NodeRef *) nr);
	nr->noderef = noderefMake();
	LOGDEBUG(stringJoin("enoderefInit:", ptrToString(nr)));
}

void enoderefDelete(ENodeRef *nr) {
	//stringFree(nr->HostName);
	LOGDEBUG(stringJoin("enoderefDelete:", ptrToString(nr)));
	noderefFree(nr->noderef);
}

void nraCheckMake() {
	LOGDEBUG("nraCheckMake called");
	if(NRA == NULL) {
		NRA = (ENodeRefArrayHandle *) arrayMake(sizeof(ENodeRef), 0, &enoderefblank, (ArrayFuncCreate) enoderefInit, (ArrayFuncDelete) enoderefDelete);
	}
	if(LNRA == NULL) {
		LNRA = (NodeRefArrayHandle *) arrayMake(sizeof(NodeRef), 0, &noderefblank, (ArrayFuncCreate) noderefMakeAt, (ArrayFuncDelete) noderefDelete);
	}
	LOGDEBUG("nraCheckMake finished");
}

void lnraCheckMake() {
	nraCheckMake();
}


//add a nodereg to the array
//makes a copy of the input hostname
ENodeRef *nraAdd(char* hostname){
	arrayInsert((ArrayHandle *)NRA, NRA->size, 1);
	NRA->data[NRA->size - 1].noderef->HostName = stringCopy(hostname);
	return &NRA->data[NRA->size - 1];
}


//searches for a node by its iTag and returns the index to it.
int nraFindNodeByITag(ITag itag) {
	int i;
	if(NRA == NULL) {
		return -1;
	}
	for(i = 0; i < NRA->size; i++) {
		if(NRA->data[i].noderef->iTag == itag) {
			return i;
		}
	}
	return -1;
}



NodeRef *lnraAdd(char *hostname) {
	arrayInsert((ArrayHandle *)LNRA, LNRA->size, 1);
	LNRA->data[LNRA->size - 1].HostName = stringCopy(hostname);
	return &LNRA->data[LNRA->size - 1];
}

void lnraDelete(int index) {
	arrayDelete((ArrayHandle *)LNRA, index, 1);
}

