// 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: LeaveNode.java
// Path: eventbase/btree
// Description: Defines the leaf node

package eventbase.btree;

public class LeafNode extends TreeNode {

  protected LeafNode next;
  protected LeafNode prev;
  private int iteratorIndex;

  public LeafNode() {
    nodeType = LEAF;
    next = null;
    prev = null;
    count = 0;
    recordArray = new LeafNodeRecord[NUMRECORD];
    for (int i = 0; i < this.NUMRECORD; i++) {
      this.recordArray[i] = new LeafNodeRecord();
    }
    iteratorIndex = -1;
  }

  // first d entries in current tree node stay, rest move to brand new node L2
  // returns the new node L2
  public TreeNode split(TreeNodeRecord r) {
    LeafNode newNode = new LeafNode();
    // typical double link list insertion operation
    newNode.next = this.next;
    if (this.next != null)
      this.next.prev = newNode;
    this.next = newNode;
    newNode.prev = this;
    // split
    for (int i = degree; i < NUMRECORD; i++) {
      newNode.recordArray[i-degree].copy(this.recordArray[i]);
      newNode.count++;
      this.recordArray[i].clearRecord();
      this.count--;
    }
    return newNode;
  }

  public LeafNodeRecord getFirstRecord() {
    return (LeafNodeRecord) recordArray[0];
  }

  public LeafNodeRecord getLastRecord() {
    if (count > 0 )
      return (LeafNodeRecord) recordArray[count-1];
    else
      return null;
  }

  // just return one record indicated by key
  // return null if record identify by specific key is not found
  public LeafNodeRecord getRecord(double key) {
    for (int i = 0; i < count; i++) {
      if (recordArray[i].getKey() == key)
        return (LeafNodeRecord)recordArray[i];
    }
    return null;
  }

  // start iterator indicated by key
  // if key doesn't exist, the iterator will be set at i
  // recordArray[i] <= key < recordArray[i+1]
  // if key is less then recordArray[i], then iterator is set at i
  // if key is greater then recordArray[count-1], then iterator is set at count
  public void getNextRecordInit (double key) {
    this.iteratorIndex = -1; // reset
    if (key < recordArray[0].getKey()) {
      this.iteratorIndex = 0;
      return;
    }
    //    System.out.println("****************** count " + count);
    if (count > 0 && key > recordArray[count-1].getKey()) {
      this.iteratorIndex = count;
      return;
    }
    for (int i = 0; i < count; i++) {
      if ((recordArray[i].getKey() <= key) &&
          ((i == count-1) || (key < recordArray[i+1].getKey()))){
        if (recordArray[i].getKey() == key)
          this.iteratorIndex = i;
        else
          this.iteratorIndex = i+1;
        return;
      }
    }
  }

  // get vaule of what iteratorIndex point at
  public LeafNodeRecord getNextRecord () {
    LeafNodeRecord retVal = null;
    if (this.iteratorIndex >= count) {
      this.iteratorIndex = -1;  // reset
      return null;
    }
    else {
      if (this.iteratorIndex >=0) {
        retVal = (LeafNodeRecord)recordArray[this.iteratorIndex];
        this.iteratorIndex++; // ahcheng - 09/02 bug fix for empty tree
      }
    }
    return retVal;
  }

  // get one value before what iteratorIndex point at
  public LeafNodeRecord getPrevRecord () {
    this.iteratorIndex--;
    if (this.iteratorIndex < 0)
      return null;
    else
      return (LeafNodeRecord) recordArray[this.iteratorIndex];
  }

  public void setIteratorToLastRecord() {
    this.iteratorIndex = count;
  }

  public void setIteratorToFirstRecord() {
    this.iteratorIndex = 0;
  }

  public int getIteratorIndex() {
    return this.iteratorIndex;
  }
}
