// 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: LinkInfoTableEntry.java
// Path: eventbase/link
// Description: defines link information table entry

package eventbase.link;
import java.text.*;
import eventbase.*;

public class LinkInfoTableEntry implements LinkInfoType{

  private double time;
  private int sourceID;
  private int targetID;
  private int linkInfoType;

  // for Bandwidth and Packet Loss Rate
  private double doubleVal = -1;

  // currently, getBytes will only be calculated once.  If value of private
  // member changes, byteVal needs to be recalculated.
  private byte [] byteVal;

  public LinkInfoTableEntry(double t, int srcID, int tgtID, int type, double val) {
    time = t;
    sourceID = srcID;
    targetID = tgtID;
    linkInfoType = type;
    doubleVal = val;
    byteVal = null;
  }

  public boolean foundLinkWanted(int srcID, int tgtID, int type) {
    if (type == linkInfoType && sourceID == srcID && targetID == tgtID)
      return true;
    else
      return false;
  }

  public double getTime() {
    return time;
  }

  public int getSourceID() {
    return sourceID;
  }

  public int getDestID() {
    return getDestID();
  }

  public int getLinkInfoType() {
    return linkInfoType;
  }

  public double getVal() {
      return doubleVal;
  }

  public boolean occursOn(LinkInfoTableEntry inEvent) {
    return (this.getTime() == inEvent.getTime());
  }

  public boolean occursEarlier(LinkInfoTableEntry inEvent) {
    return (this.getTime() < inEvent.getTime());
  }

  public boolean occursLater(LinkInfoTableEntry inEvent) {
    return (this.getTime() > inEvent.getTime());
  }

  public void print() {
    // Number Format
    DecimalFormat numformat = new DecimalFormat();
    numformat.setMaximumFractionDigits(6);
    System.out.print(numformat.format(time) + " " + time + " " + sourceID + " " + targetID + " " + linkInfoType + " ");
    System.out.println(doubleVal);
  }

  // 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.sourceID);
      MemoryManager.insertInteger(byteVal, 12, this.targetID);
      MemoryManager.insertInteger(byteVal, 16, this.linkInfoType);
      MemoryManager.insertDouble(byteVal, 20, this.doubleVal);
    }
    return byteVal;
  }

  public static LinkInfoTableEntry extractFromBytes(byte[] buffer) {
    if (buffer == null) {
      System.err.println("ERROR: LinkInfoTableEntry() Unable to extract bytes");
      return null;
    }
    double t = MemoryManager.bytesToDouble(buffer, 0);
    int srcID = MemoryManager.bytesToInteger(buffer, 8);
    int tgtID = MemoryManager.bytesToInteger(buffer, 12);
    int type = MemoryManager.bytesToInteger(buffer, 16);
    double val = MemoryManager.bytesToDouble(buffer, 20);
    return new LinkInfoTableEntry(t, srcID, tgtID, type, val);
  }
}