package tree;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Each object in the Tree class represents a single node;
 * however, nodes are linked together, so that any node may
 * be considered as the "root" of a complete tree.
 * 
 * @author Dave Matuszek
 * @author  TODO: put your name here as second author)
 * @version Jan 20, 2010
 * @param <V> The type of values held in the Tree.
 */
public class Tree<V> {

    /**
     * Creates a Tree node with the given value and zero
     * or more children.
     * 
     * @param value The value to put in this node.
     * @param children The nodes to add as children.
     */
    public Tree(V value, Tree<V>... children) {
        
    }
    
    /**
     * Returns the value in this node of the Tree.
     * @return The value in this node.
     */
    public V getValue() {
        return null;
    }
    
    /**
     * Sets the value in this node of the Tree.
     * @param value The value to be stored in this node.
     */
    public void setValue(V value) {
        
    }
    
    /**
     * Adds each node in <code>children</code> as a new child
     * of this Tree, after any existing children. The nodes
     * of <code>children</code> are added in order; if any
     * addition would result in a loop, an exception will be
     * thrown, and this Tree will be left in a partially
     * modified state.
     * 
     * @param children The nodes to be added as children of
     *    this node.
     * @throws IllegalArgumentException If an illegal index is
     *    given, or if adding some child would create a loop.
     */
    public void addChildren(Tree<V>... children )
            throws IllegalArgumentException {
        
    }
    
    /**
     * Adds newChild as the new index-th child of this tree
     * (counting from zero), provided that the resultant tree
     * is loop-free. The child previously at this index, and
     * all subsequent children, are "shifted right" (their
     * index is increased) to make room for the new child.
     *
     * @param index The position at which to insert the node.
	 * @param newChild The node to be inserted.
     * @throws IllegalArgumentException If an illegal index is
     *    given, or if adding the child would create a loop.
     */
    public void addChild(int index, Tree<V> newChild)
            throws IllegalArgumentException {
        
    }
    
    /**
     * Removes and returns the index-th child of this tree (as a
     * complete subtree), or throws a NoSuchElementException if
     * the index is illegal.
     * 
     * @param index The position of the child to be removed.
     * @return The subtree that is removed.
     * @throws NoSuchElementException If there is no such child.
     */
    public Tree<V> removeChild(int index)
            throws NoSuchElementException {
        return null;
    }
    
    /**
     * Returns the first child of this tree (which may
     * be <code>null</code>).
     * @return The first child of this node, or <code>null</code>.
     */
    public Tree<V> firstChild() {
        return null;
    }

    /**
     * Returns the first last of this tree (which may
     * be <code>null</code>).
     * @return The last child of this node, or <code>null</code>.
     */
    public Tree<V> lastChild() {
        return null;
    }
    
    /**
     * Returns the index-th child of this tree (counting from
     * zero, as with arrays). Throws a NoSuchElementException
     * if there is no such child (that is, if index is less
     * than zero or greater than or equal to the number of
     * children).
     * 
     * @param index The index of the desired child.
     * @return The index-th child.
     * @throws NoSuchElementException if there is no such child.
     */
    public Tree<V> child(int index)
            throws NoSuchElementException {
        return null;
    }
    
    /**
     * Returns the number of (immediate) children of this node.
     * @return The number of children of this node.
     */
    public int numberOfChildren() {
        return -1;
    }
    
    /**
     * Returns <code>true</code> if this node has no children.
     * @return <code>true</code> if this node is a leaf.
     */
    public boolean isLeaf() {
        return true;
    }
    
    /**
     * Returns <code>true</code> if this tree contains the
     * given node (not an equal node). The root of this tree
     * is included in the recursive search.
     * 
     * @param node The node to be searched for.
     * @return <code>true</code> if the node is found.
     */
    public boolean contains(Tree<V> node) {
        return true;
    }
    
    /**
     * Returns an iterator for the children of this node.
     * @return An iterator over the children of this node.
     */
    public Iterator<Tree<V>> children() {
        return null;
    }
    
    /**
     * Returns <code>true</code> if (1) the given object is
     * a Tree, and (2) the value fields of the two trees are
     * equal, and (3) each child of one Tree equals the
     * corresponding child of the other Tree.
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object object) {
        return false;
    }
    
    /**
     * Returns a single line representation of this Tree, where
     * each node is represented by the String representation of
     * its value, and the children of each node are separated by
     * spaces and enclosed in parentheses.
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return null;
    }
    
    /**
     * Returns a multiline representation of this Tree. Each
     * line contains the toString() representation of the value
     * in that node, terminated with a newline (\n). Each child
     * is indented two spaces under its parent.
     * @return A multiline representation of this Tree.
     */
    public String toLongString() {
        return null;
    }
}
