/**
 * A node used to implement binary trees.  Each node keeps track of its level
 * and the tree in which it is stored.  That way, it is easier to update both
 * node and tree.  If the associated tree is null, the node is no longer part
 * of the tree.
 */
public class BinaryTreeNode {
  // +--------+--------------------------------------------------
  // | Fields |
  // +--------+

  /** The parent of this node.  Set to null when it's the root. Cannot be changed. */
  protected BinaryTreeNode parent;
  /** The left child of this node.  Set to null if it has no left child. */
  protected BinaryTreeNode left;
  /** The right child of this node.  Set to null if it has no right child. */
  protected BinaryTreeNode right;
  /** The contents of this node. */
  protected Object contents;

  // +--------------+--------------------------------------------
  // | Constructors |
  // +--------------+

  /**
   * Create a new node with a specified parent and value.  If the parent
   * is null, assumed to be the root.
   * Pre: Parent is non-null.
   * Post: Node is created.
   * Post: While the parent link has been set, the child link of the parent
   *   has not been set (since we don't know if this is a left or right child).
   */
  public BinaryTreeNode(BinaryTreeNode parent, Object value) {
    this.parent = parent;
    this.contents = value;
    this.left = null;
    this.right = null;
  } // BinaryTreeNode(BinaryTreeNode, Object)

  // +-----------+-----------------------------------------------
  // | Accessors |
  // +-----------+

  /** Get the contents of the current node. */
  public Object getContents() {
    return this.contents;
  } // getContents()

  /** Get the left child of the current node. */
  public BinaryTreeNode getLeft() {
    return this.left;
  } // getLeft()

  /** Get the parent of the current node. */
  public BinaryTreeNode getParent() {
    return this.parent;
  } // getParent()
 
  /** Get the right child of the current node. */
  public BinaryTreeNode getRight() {
    return this.right;
  } // getRight()

  // +-----------+-----------------------------------------------
  // | Modifiers |
  // +-----------+

  /** 
   * Delete this node and every node below it.  Returns the number of nodes
   * deleted.
   */
  public int delete() {
    int numDeleted = 1;
    parent = null;
    if (left != null) {
      numDeleted += left.delete();
      left = null;
    }
    if (right != null) {
      numDeleted += right.delete();
      right = null;
    }
    contents = null;
    return numDeleted;
  } // delete()

  /** Set the contents of this node. */
  public void setContents(Object newContents) {
    this.contents = newContents;
  } // setContents()

  /** Set the left child of this node. */
  public void setLeft(BinaryTreeNode newLeft) {
    this.left = newLeft;
  } // setLeft(BinaryTreeNode)

  /** Set the right child of this node. */
  public void setRight(BinaryTreeNode newRight) {
    this.right = newRight;
  } // setRight(BinaryTreeNode)
} // class BinaryTreeNode

