/*
 * 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.
 */

#ifndef _PEER_H
#define _PEER_H

#include "node.h"

#ifdef _WENGO
#include "p2pp/common/types.h"
#include "p2pp/msg/msgheader.h"
#include "p2pp/bigint/bigint.h"
//#include "p2pp/table/chordrtable.h"
#include "p2pp/node/rmanager.h"
#include "p2pp/node/mainthelper.h"
#endif

#ifndef _WENGO
#include "types.h"
#include "msgheader.h"
#include "bigint.h"
//#include "chordrtable.h"
#include "rmanager.h"
#include "mainthelper.h"
#include "stimanager.h"
#endif


#include <list>
using namespace std;


enum PeerState {ePINITIAL=0, ePBOOTSTRAP, ePBOOTSTRAPSENT, ePLOOKUPSTUN, ePJOIN, ePCONNECTED, ePFAILURE, ePDISCONNECTED};
enum PeerSubState {eS_PNONE=0, eS_PJOINCON, eS_PTUPDATE, eS_PKASENT, eS_INSERT, eS_LOOKUP};

class STIManager;


class Peer : public Node {


  friend class RManager;
  friend class MaintHelper;
  friend class STIManager;

 public:
  RManager m_objRM;
  MaintHelper m_objMH;  

 protected:
  uint32 m_uiTransId;  
  STIManager m_objSTI;

  //node timers
  uint32 m_RMT;  //routing table maintenance timer (in seconds)
  uint32 m_KAT;  //keep-alive timer (in seconds)
  uint32 m_TT;   //table timer. generic timer
  
  list<LObject> m_LO;

  list<peerinfo>::iterator m_itrSTind; //iterator for storing the iterator for current STUN server

 public:  
  static enum PeerState m_eState;  
  static enum PeerSubState m_eSubState;

  static list<peerinfo> m_BSP;

  static char8 m_STUN_IP[IPADDRLEN];
  static uint16 m_STUN_PORT;
  
 private:
  virtual uint32 getNextHop(uchar* peerid, uint32 len, struct peerinfo& stP);
  

 public:

  void ComposeBootstrap();

  void ComposeJoin(struct peerinfo stPeer);
  void ComposeJoin(struct peerinfo stP, transtype tt, string& strtransid, struct message& msg);

  void ComposeJoinResp(int32 respCode, struct peerinfo stPSelf, struct peerinfo stPNext, char* pchIP, int32 port, transtype tt);  
  void ComposeJoinResp(char* pchIP, int32 port, transtype tt, struct message& msg);


  void ComposeExchangeTable(struct peerinfo stPeer);
  void ComposeExchangeTableWithLookupPeer(struct peerinfo stP, const struct LObject& objLO, string& strtransid);
  void ComposeKeepAlive(struct peerinfo stPeer);

  void ComposeKeepAliveResp(char* pchIP, int32 port, transtype tt);
  void ComposeExchangeTableResp(list<peerinfo>& lstP, char* pchIP, int32 port, transtype tt);


  void ComposePublishObject(struct peerinfo lstP, const LObject& objLO, string& strtransid);
  void ComposePublishObject(struct peerinfo lstP, const LObject& objLO, string& strtransid, struct message& msg, transtype tt);

  void ComposePublishObjectResp(int32 respCode, struct peerinfo stPSelf, struct peerinfo stPNext, char* pchIP, int32 port, transtype tt, struct timeval expires, struct message& msg);
  void ComposePublishObjectResp(char* pchIP, int32 port, transtype tt, struct message& msg);


  void ComposeLookupObject(struct peerinfo lstP, const LObject& objLO, string& strtranid);
  void ComposeLookupObject(struct peerinfo lstP, const LObject& objLO, string& strtransid, struct message& msg, transtype tt);

  void ComposeLookupObjectResp(int32 respCode, struct peerinfo stPSelf, struct peerinfo stPNext, char* pchIP, int32 port, transtype tt, LObject& objLO);
  void ComposeLookupObjectResp(char* pchIP, int32 port, transtype tt, struct message& msg);


  void ComposeLookupPeer(struct peerinfo lstP, const struct LObject& objLO, string& strtransid, struct message& msg, transtype tt);
  void ComposeLookupPeer(struct peerinfo stPeer, const LObject& objLO, string& strtranid);  
  void ComposeLookupPeerResp(list<struct peerinfo> lstP, int num, char* pchIP, int32 port, transtype tt, int32 respCode);  

  void ComposeACK(char* pchIP, uint16 port);


  void ComposeDiagnostics(const LObject& objLO, string& strtransid);
  void ComposeDiagnosticsResp(list<peerinfo>& lstP, list<resourceobject>& lstRes, char* pchIP, int32 port, transtype tt);

  void ComposeSet(struct LObject& objLO, struct nodeval& stnodeval, string& strtransid);
  void ComposeReset(struct LObject& objLO, struct nodeval& stnodeval, string& strtransid);
  void ComposeResetResp(char* pchIP, int32 port, transtype tt);
  void ComposeSetResp(char* pchIP, int32 port, transtype tt);

  //For bootstrap purposes. Check if bootstrap node address is present
  //If none, then we are the first node
  int32 CreateBNList(list<peerinfo>& l_BSP) ;
  int32 getSelfPeer(struct peerinfo& stP);
  int32 getSelfID();

  int32 SendACK(char* pchIP, uint16 port);
  
 public:
  Peer();
  virtual ~Peer();

  virtual void Initialize();
  virtual void OnTimer();
  virtual int32 OnReceive(uchar* buf, int len, char* pchIP, int32 port, transtype tt);


  virtual int32 PublishObject (char8* pchKey, uint32 klen, char8* pchValue, uint32 vlen, transtype tt, void* (*)(void*, int32), void* pApp );
  virtual int32 LookupObject (char8* pchKey, uint32 klen, transtype tt, void* (*)(void*, int32), void* pApp, void *pConference );
  virtual int32 LookupUser (char8* pchKey, uint32 klen, transtype tt, void* (*)(void*, int32), void* pApp, void *pConference);
  virtual int32 LookupSIP (char8* pchKey, uint32 klen, transtype tt, void* (*)(void*, int32), void* pApp, void *pConference);

  virtual int32 RemovePeer(const char* pchIP, const uint32 port) {return 0;}

  //Debugging functions for remotely obtaining state of a node
  virtual int32 GetRT(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*)(void*, int32 respcode), void* pApp);
  virtual int32 GetNT(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*)(void*, int32 respcode), void* pApp);
  virtual int32 GetRO(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*)(void*, int32 respcode), void* pApp);
  virtual int32 GetRelayList(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*)(void*, int32 respcode), void* pApp);
  virtual int32 GetTurnAlloc(char8* pchIP, uint32 ilen, uint16 port, transtype tt, void* (*)(void*, int32 respcode), void* pApp);

  //Change user ID
  virtual int32 ChangeUserID(char8* pchID, uint32 ilen, void* (*)(void*, int32 respcode), void* pApp);

  //Set specific values such as bw, cpuutil, memory for program and machine
  virtual int32 Set(char8* pchIP, uint32 ilen, uint16 port, transtype tt, struct nodeval& stnv, int32 isSet, void* (*)(void*, int32 respcode), void* pApp);

  virtual int32 Disconnect(void* (*callback)(void*, int32 respcode), void* pApp);

  //Insert stP into the table.  
  virtual int32 Insert(struct peerinfo& stP, int32 updateKA) {return 1;};
  virtual int32 Insert(list<peerinfo>& lstP, int32 updateKA) {return 1;};
  virtual int32 Insert(struct peerinfo& stP, int32 updateKA, uint16 stunPort) {return 1;};

  //Debugging functions for checking the local state
  virtual void ShowRT() {};
  virtual void ShowNT() {};
  virtual void ShowRO() {};
  virtual void ShowCP() {};

  virtual void ShowCPlist() {};
  virtual void ShowRelayServerList() {};
  virtual void ShowTURNAlloc() {};
  virtual void ShowRelayAllocations() {}

  //Get SIP object (Default return value =0, i.e. no SIP object)
  virtual int32 GetSIPObject(struct resourceobject& stRo) {return 0;}

  virtual void UpdateRelayList(const list< struct peerinfo> lstP) {}

  virtual int GetStunServerPort() {return 0;}
};

#endif

