// Carnegie Mellon University
//   Information Networking Institute and
//   School of Computer Science
//
// Master Thesis: A Monitoring Tool for Overlay Network
// By: TungFai Chan and Annie Cheng
//
// File: VirtualRoutingTableEntry.java
// Path: eventbase/routing
// Description: record entries in virtual routing table

package eventbase.routing;
import java.text.*;
import eventbase.*;

public class VirtualRoutingTableEntry {

  private double time;
  private int destID;
  private int nextHopID;
  private OverlayHost dest;
  private OverlayHost nextHop;
  private int cost;
  private int deadFlg;
  private int numChild;
  private String[] childList;
  private int [] childIDList;
  private int curChildCount;

  // currently, getBytes will only be calculated once.  If value of private
  // member changes, byteVal needs to be recalculated.
  private byte [] byteVal;

  public VirtualRoutingTableEntry(double t, int destHostID, int next, int delay, int dead, int childCount) {
    time = t;
    destID = destHostID;
    nextHopID = next;
    cost = delay;
    byteVal = null;
    deadFlg = dead;
    dest = null;
    nextHop = null;
    numChild = childCount;
    if (numChild != -1) {
	childList = new String[childCount];
	childIDList = new int[childCount];
    }
    else {
	childList = null;
	childIDList = null;
    }
    curChildCount = 0;
  }

  public void setNumChildren(int childCount) {
      curChildCount = 0;
      childList = null;
      childIDList = null;
      childList = new String[childCount];
      childIDList = new int [childCount];
      numChild = childCount;
  }
    
  public void addChild(String child, int childID) {
      childList[curChildCount] = child;
      childIDList[curChildCount] = childID;
      curChildCount++;
  }

  public boolean gotAllChildren() {
      return (curChildCount == numChild);
  }
    
  public double getTime() {
    return time;
  }

  public int getDestID() {
    return destID;
  }

  public int getNextHopID() {
    return nextHopID;
  }

  public void setOverlayHostForDisplay(OverlayHost destHost, OverlayHost next) {
    this.dest = destHost;
    this.nextHop = next;
  }

  public OverlayHost getDest() {
    return dest;
  }

  public OverlayHost getNextHop() {
    return nextHop;
  }

  public int getCost() {
    return cost;
  }

  public int getDeadFlg() {
    return deadFlg;
  }

  public int getNumChild() {
     return numChild;
  }

  public String[] getChildList() {
    return childList;
  }

    public int[] getChildIDList() {
	return childIDList;
    }

  public void print() {
    DecimalFormat numformat = new DecimalFormat();
    numformat.setMaximumFractionDigits(6);
    System.out.println (numformat.format(time) + " " + destID + " " + nextHopID
                        + " " + cost + " " + deadFlg + " " + numChild);
    if (childList != null) {
	System.out.print ("Children : ");
	for (int i = 0; i < numChild; i++)
	    System.out.print (childList[i] + " ");
	System.out.println();
    }
  }

  // Caution: this function needs to be modified if set functions are allowed
  // currently, getBytes will only be calculated once.  If value of private
  // member changes, byteVal needs to be recalculated.
  public byte[] getBytes() {
    if (byteVal == null){
      byteVal = new byte[MemoryManager.getBytesPerRecord()];
      MemoryManager.insertDouble(byteVal, 0, this.time);
      MemoryManager.insertInteger(byteVal, 8, this.destID);
      MemoryManager.insertInteger(byteVal, 12, this.nextHopID);
      MemoryManager.insertInteger(byteVal, 16, this.cost);
      MemoryManager.insertInteger(byteVal, 20, this.deadFlg);
      MemoryManager.insertInteger(byteVal, 24, this.numChild);
    }
    return byteVal;
  }

  public static VirtualRoutingTableEntry extractFromBytes(byte[] buffer) {
    if (buffer == null) {
      System.err.println("ERROR: VirtualRoutingTableEntry() Unable to extract bytes");
      return null;
    }
    double t = MemoryManager.bytesToDouble(buffer, 0);
    int destid = MemoryManager.bytesToInteger(buffer, 8);
    int nexthopid = MemoryManager.bytesToInteger(buffer, 12);
    int cost = MemoryManager.bytesToInteger(buffer, 16);
    int dead = MemoryManager.bytesToInteger(buffer, 20);
    int numChild = MemoryManager.bytesToInteger(buffer, 24);
    return new VirtualRoutingTableEntry(t, destid, nexthopid, cost, dead, numChild);
  }

  // 09/06/00 - ahcheng - support network trigger update
  public void update(int destid, int next, int delay, int dead) {
    if (destid != this.destID) {
      System.err.println("VirtualRoutingTableEntry: update Error");
      return;
    }
    this.nextHopID = next;
    this.cost = delay;
    this.deadFlg = dead;
  }
}
