/*
 * Copyright (C) 2008 The Trustees of Columbia University in the City of New York. 
 * All rights reserved.
 *
 * See the file LICENSE included in this distribution for details.
 */

#include "node.h"
#include "kadpeer.h"
#include "cpuutil.h"
//#include "chordpeer.h"

#include <string.h>
#include <stdio.h>

extern CpuUtil *gCpuUtilization;

uchar  Node::m_ID[ID_MAX];
//uint16 Node::m_TCP_PORT; //TCP listening port
//uint16 Node::m_UDP_PORT; //UDP listening port
//enum p2palg Node::m_P2P; //P2P algorithm
//enum halg Node::m_HASH_ALG;
//int32 Node::m_HASH_SIZE; //size in bytes.
//int32 Node::m_BASE;      //base 2, 4, 16, 32 etc.
//int32 Node::m_REC;       //recursive / iterative flag recursive=1, iterative=0
//int32 Node::m_PARALLEL;
  
//int32 Node::m_NODE_TYPE;

//char8 Node::m_BOOT_IP[IPADDRLEN];
//uint16 Node::m_BOOT_PORT;
//uchar Node::m_USERID[ID_MAX];

//Transport object
Transport* Node::m_pobjTransport;

//Routing and neighbor table manipulation
list<peerinfo> Node::m_tempNT;		//Temporary NT. Used during maintainance.
list<peerinfo> Node::m_tempRT;		//Temporary RT. Used during maintainance.
Table* Node::m_pRT;			        //Pointer to the local Routing table
Table* Node::m_pNT;		                //Pointer to the local Neighbor table.

//Application call back
void* Node::m_pApp;
void* (*Node::appCallBack)(void*, int32);
void* (*Node::onTimerCallback)(void*);

//Transaction map
map<string, Transaction*> Node::m_TMap;

Node::Node() {
  
}

Node::~Node() {
  
}

void Node::setID(char* pchID) {
  strcpy((char*)m_ID, pchID); //unsafe
}//setID

void Node::setUSERID(uchar* pchUID) {
  strcpy((char*)m_USERID, (char*)pchUID);
}

char* Node::getUSERID() {
  return (char*)m_USERID;
}//getUSERID

void Node::setTCPPort(int32 iPort) {
  m_TCP_PORT = iPort;
}//setTCPPort

void Node::setUDPPort(int32 iPort) {
  m_UDP_PORT = iPort;
}//setUDPPort

void Node::setP2P(char* pchP2P) {
  if(0 == strcasecmp("Chord",pchP2P)) {
    m_P2P = eCHORD;
  } else if(0 == strcasecmp("Kademlia", pchP2P)) {
    m_P2P = eKADEMLIA;
  }
}//setP2P

p2palg Node::getP2P() {
  return m_P2P;
}//getP2P

void Node::setHashAlg(char* pchAlg) {
  if(0 == strcasecmp("None", pchAlg)) {
    m_HASH_ALG = eNONE;
  }
}//setHashAlg


void Node::setHashSize(int32 iSize) {
  m_HASH_SIZE = iSize;
}//setHashSize


void Node::setRec(int32 iRec) {
  m_REC = iRec;
}//setItr


void Node::setParallel(int32 iParallel) {
  m_PARALLEL = iParallel;
}//setParallel




void Node::setTransport(Transport* pobjTransport) {
  m_pobjTransport = pobjTransport;
}//setTransport

Transport* Node::getTransport() {
  return m_pobjTransport;
}//setTransport


void Node::setMode(char* pchMode) {

  if(0 == strcasecmp("BOOTSTRAP", pchMode)) {
    m_NODE_TYPE = eBOOTSTRAP_SERVER;
  } else if(0 == strcasecmp("PEER", pchMode)) {
    m_NODE_TYPE = ePEER;
  } else if(0 == strcasecmp("CLIENT", pchMode)) {
    m_NODE_TYPE = eCLIENT;
  }
  
}//setMode


int32 Node::getNodeType() {
  return m_NODE_TYPE;
}//getNodeType

void Node::setConfigParams(const P2PConfig& objConfig) {
  
  //memcpy(m_ID, objConfig.m_ID, ID_MAX);
  setUSERID((uchar*)objConfig.m_USERID);
  m_TCP_PORT = objConfig.m_TCP_PORT;
  m_UDP_PORT = objConfig.m_UDP_PORT;
  m_P2P = objConfig.m_P2P; 
  m_HASH_ALG = objConfig.m_HASH_ALG;
  m_HASH_SIZE = objConfig.m_HASH_SIZE; 
  m_BASE = objConfig.m_BASE;
  m_REC = objConfig.m_REC;
  m_PARALLEL = objConfig.m_PARALLEL;
  m_NODE_TYPE = objConfig.m_NODE_TYPE;

  strncpy(m_BOOT_IP, objConfig.m_BOOT_IP, IPADDRLEN);
  m_BOOT_PORT = objConfig.m_BOOT_PORT;

}//setConfigParams




void Node::Initialize() {

  m_pobjTransport->Initialize(m_TCP_PORT, m_UDP_PORT);
}//Initialize


void Node::OnTimer() {  
  if(gCpuUtilization) {
    gCpuUtilization->Recompute();
  }  
}


int32 Node::OnReceive(uchar* buf, int len, char* pchIP, int32 port, transtype tt) {
  return 1;
}


int32 Node::Disconnect(void* (*callback)(void*, int32 respcode), void* pApp) {
  return 1;
}//Disconnect


void Node::setCallBack(void* (*callback)(void*, int32), void* pApp) {

  appCallBack = callback;
  m_pApp = pApp;

}//setCallBack

void Node::setOnTimerCallback(void* (*callback)(void*) ) {
  onTimerCallback = callback;
}//setOnTimerCallback

