///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// Copyright (C) 2006 by Intel Coproration and Carnegie Mellon University    //
// Contacts: casey.j.helfrich @ intel.com                                    //
//           bdr @ cs.cmu.edu                                                //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#ifndef __DPRHIERARCHY_H
#define __DPRHIERARCHY_H

#include "Hierarchy.hxx"

class DPRHierarchy;

class LandmarkMsg : public Message {
public:
  LandmarkMsg(DPRHierarchy* _hierarchy, vector<catomID> dest, Message* _payload);
  LandmarkMsg(MailboxID _mailboxID, vector<catomID> dest, Message* _payload);
  
  vector<catomID> destination;
  Message* payload;

  virtual void* clone() { return new LandmarkMsg(mailboxID, destination, (Message*)payload->clone()); }
};

class LandmarkBeacon : public Message {
public:
  LandmarkBeacon(DPRHierarchy* _hierarchy, catomID _id, long int _beaconID, unsigned int _visDistance, unsigned int _distanceSoFar, int _level, catomID _parent);
  LandmarkBeacon(MailboxID _mailboxID, catomID _id, long int _beaconID, unsigned int _visDistance, unsigned int _distanceSoFar, int _level, catomID _parent);

  catomID id;
  long int beaconVersionID;
  unsigned int visDistance;
  unsigned int distanceSoFar;
  int level;
  catomID parent;

  virtual void* clone() { return new LandmarkBeacon(mailboxID, id, beaconVersionID, visDistance, distanceSoFar, level, parent); }
};


class DPRHierarchy : public Hierarchy {
  friend class LandmarkMsg;
  friend class LandmarkBeacon;

public:
  DPRHierarchy(catomID _hostCatom, string _hierarchyName);
  virtual ~DPRHierarchy();

protected:
  virtual void simulationStart();
  virtual void dumpStats();
  virtual void endTick();

  virtual bool sendMsgToParent(Message* msg);

private:
  string hierarchyMessageBox;
  string landmarkBeaconBox;

  map<catomID, featureID> routingTable;
  map<catomID, long> beaconIDs;
  map<catomID, unsigned long> beaconHopcounts;
  unsigned int visibilityDistance;
  long int lastAnnouncementTime;
  long unsigned int nextBeaconVersionID;
  set<catomID> peers;

  bool hierarchyMessageHandler(Message* _msg);
  bool landmarkBeaconHandler(Message* _msg);
  bool updateLandmarkRoutingTables(catomID _landmarkID, featureID _contact, long _msgID, unsigned long _hopcount);
  void landmarkAnnounce();
  void promoteSelf();
};

#endif
