#ifndef _RMANAGER_H
#define _RMANAGER_H

#ifndef _WENGO
#include "types.h"
#include "msgheader.h"
#include "bigint.h"
#endif

#ifdef _WENGO
#include "p2pp/common/types.h"
#include "p2pp/msg/msgheader.h"
#include "p2pp/bigint/bigint.h"
#endif

#include <map>
using namespace std;


//The keep-alive time is 30 seconds.
#define EXP_TIME 30
//The default expire time of a resource is 5 minutes.
#define EXP_TIME_RVAL 300


enum diag_type {eGET_NT=0, eGET_RT, eGET_RO, eGET_NONE, eGET_TURNALLOC, eGET_RELAYLIST};

class Peer;

//Lookup object. (legacy name)
//This structure stores the information about the inprogress
//transaction. This information is then helpful to send
//responses upstream (recursive forwarding) and to call
//callback functions.

struct LObject {
  string strKey;
  string strVal;

  enum diag_type diagtype;
  enum content_type conttype;
  enum reqoritype ritype;
  int32 changeID; //whether we need to change our ID
  int32 disconnect; //disconnect
  int32 ttl;

  struct rlookup strl;
  list<resourceobject> lstro;
  list<peerinfo> lstrt;
  list<peerinfo> lstnt;
  struct bw stbw;
  struct cpuutil stcpuutil;   //program cpu utilization
  struct cpuutil sttcpuutil;  //machine cpu utilization
  list<turnalloc> lstta;
  list<peerinfo> lstrl;

  struct resourceobject stro;
  struct plookup stpl;

  void* pApp;
  void* (*callback)(void*, int32);

  //For recursive forwarding
  char8 pchIP[IPADDRLEN];
  uint16 port;
  enum transtype tt;
  
  int32 isOrig;   //isOrig=1 if we sent the request and not forwarded it. 0 otherwise.

  //for callback function
  Peer *pPeer;

  struct timeval senttime;  //to calculate RTT

  struct nodeval stnv;      //used in SET, RESET methods
public:
  LObject();
  ~LObject();
};




struct IRO3 {
  struct resourceobject stro;
  struct peerinfo stP;
  struct timeval expt;
  string strtransid;
};

struct classcomp{
  bool operator()(const string& lhs, const string& rhs) const
  {return false;}
};

struct IRO2 {
  //owner
  map<string, IRO3, classcomp> m_OMap;
  //map<string, IRO3> m_OMap;
};


struct IRO1 {
  //type
  map<int32, IRO2> m_YMap;
};


class RManager {

 private:
    Peer* m_pPeer;

 public:

  //Publish table
  multimap<string, IRO3> m_PT;

  //Resource table
  map<string, IRO1> m_RT;
  
  //Inprogress table
  map<string, LObject> m_IP;

  //Replicate table
  map<string, list<IRO3> > m_REPT;


 public:
  RManager();
  ~RManager();

  void setParams(Peer* pPeer);

  void getResTable(list<resourceobject >& lstro);
  void getResTable(list<resourceobject >& lstro, transtype tt);

  int32 findLocal(struct LObject& objLO);

  int32 LookupUser(char8* pchUser, int32 len, enum transtype tt, void* (*callback)(void*, int32), void* pApp);
  int32 LookupObject(char8* pchKey, int32 klen, enum transtype tt, void* (*callback)(void*, int32), void* pApp);
  int32 LookupSIP(char8* pchUser, int32 len, enum transtype tt, void* (*callback)(void*, int32), void* pApp);

  int32 LookupSTI(struct peerinfo& stNP, enum transtype tt);
  int32 LookupStunPort(struct peerinfo& stNP, enum transtype tt);

  int32 OnLookupObjectRequest(struct message& msg, char* pchIP, int32 port, enum transtype tt);
  int32 OnLookupObjectResponse(struct message& msg) ;


  int32 InsertinRT(const LObject& objLO, struct timeval expires, const struct peerinfo& stP);
  int32 InsertinPT(const LObject& objLO, struct timeval expires, const string& strtransid);

  int32 UpdatePT(struct message& msg);
  int32 UpdatePT(string& strtransid);

  int32 PublishUserInfo(char8* pchUser, uint32 len, enum transtype tt);
  int32 RePublishUserInfo();
  int32 PublishObject(char8* pchKey, uint32 klen, char8* pchValue, uint32 vlen, enum transtype tt, void* (*)(void*, int32), void* pApp);
  int32 OnPublishObjectRequest(struct message& msg, char* pchIP, int32 port, enum transtype tt);
  int32 OnPublishObjectResponse(struct message& msg);

  int32 ChangeUserID(char8* pchID, int32 len);


  int32 OnTimer();
  int32 OnPublishTimer();
  int32 OnRTTimer();

  int32 OnTransactionTimeout(enum msgtype mtype, enum reqoritype ritype, string strtransid, char* pchIP, int32 port);

  void ShowRO();

  void Disconnect();
};


#endif
