/*
 * DiffNode.java
 *
 * Created on May 24, 2006, 2:53 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package usda.weru.util.diff;

import java.util.*;

/**
 *
 * @author Joseph Levin
 */
public class DiffNode implements Iterable <DiffNode>{
    private DiffNode c_parent;
    private Object c_a;
    private Object c_b;
    private int c_diff;
    private String c_text;
    
    private boolean c_buildFlag;
    private boolean c_diffFlag;
    
          
    
    private List<DiffNode> c_childNodes;

	/**
	 *
	 */
	public DiffNode() {
        init();
    }

	/**
	 *
	 * @param text
	 * @param a
	 * @param b
	 */
	public DiffNode(String text, Object a, Object b) {
        init();
        c_text = text;
        c_a = a;
        c_b = b;        
    }

	/**
	 *
	 * @param a
	 * @param b
	 */
	public DiffNode(Object a, Object b) {
        init();        
        c_a = a;
        c_b = b;        
    }
    
    private void init(){
        c_childNodes = new Vector <DiffNode> ();
        c_diff = Differ.DIFF_UNKNOWN;
        c_buildFlag = false;
        c_diffFlag = true;
    }

	/**
	 *
	 * @return
	 */
	public Object getA(){
        return c_a;
    }

	/**
	 *
	 * @return
	 */
	public Object getB(){
        return c_b;
    }

	/**
	 *
	 * @param a
	 */
	public void setA(Object a){
        c_a = a;
    }

	/**
	 *
	 * @param b
	 */
	public void setB(Object b){
        c_b = b;
    }

	/**
	 *
	 * @param a
	 * @param b
	 */
	public void queueChild(Object a, Object b){
        DiffNode child = new DiffNode(a, b);
        child.setBuildFlag(true);
        addChild(child);
    }

	/**
	 *
	 * @param index
	 * @param a
	 * @param b
	 */
	public void queueChild(int index, Object a, Object b){
        DiffNode child = new DiffNode(a, b);
        child.setBuildFlag(true);
        addChild(index, child);
    }

	/**
	 *
	 * @return
	 */
	public int getChildCount(){
        return c_childNodes.size();
    }

	/**
	 *
	 * @return
	 */
	public int getChildCountRecursive(){
        int childCount = getChildCount();;
        for (DiffNode child : this){
            childCount += child.getChildCountRecursive();
        }
        return childCount;
    }

	/**
	 *
	 * @param child
	 */
	public void addChild(DiffNode child){
        //You can't add yourself, will cause loop problems.
        if (child == this) return;
        c_childNodes.add(child);
        child.setParent(this);
    }

	/**
	 *
	 * @param text
	 * @param a
	 * @param b
	 * @return
	 */
	public DiffNode addChild(String text, Object a, Object b){
        DiffNode child = new DiffNode(text, a, b); 
        addChild(child);                
        return child;
    }

	/**
	 *
	 * @param index
	 * @param text
	 * @param a
	 * @param b
	 * @return
	 */
	public DiffNode addChild(int index, String text, Object a, Object b){
        DiffNode child = new DiffNode(text, a, b); 
        addChild(index, child);        
        return child;
    }

	/**
	 *
	 * @param index
	 * @param child
	 */
	public void addChild(int index, DiffNode child){
        c_childNodes.add(index, child);      
        child.setParent(this);
    }

	/**
	 *
	 * @param index
	 * @return
	 */
	public DiffNode getChildAt(int index){
        return c_childNodes.get(index);
    }

	/**
	 *
	 * @return
	 */
	@Override
    public ListIterator<DiffNode> iterator(){
        return c_childNodes.listIterator();
    }

    
    //TODO: Add node was diffed event code

	/**
	 *
	 * @param diff
	 */
	    public void setDiff(int diff){
        c_diff = diff;
    }

	/**
	 *
	 * @return
	 */
	public int getDiff(){
        return c_diff;
    }

	/**
	 *
	 * @return
	 */
	public int getDiffRecursive(){
        int diff = getDiff();
        for (DiffNode child : this){
            diff = DiffEngine.bitFlagAdd(diff, child.getDiffRecursive());
        }
        return diff;
    }

	/**
	 *
	 * @return
	 */
	public String getText(){
        return c_text;
    }

	/**
	 *
	 * @param text
	 */
	public void setText(String text){
        c_text = text;
    }

	/**
	 *
	 * @param list
	 */
	public void setBuildFlag(boolean list){
        c_buildFlag = list;
    }

	/**
	 *
	 * @return
	 */
	public boolean getBuildFlag(){
        return c_buildFlag;
    }

	/**
	 *
	 * @return
	 */
	public boolean getBuildFlagRecursive(){
        if (getBuildFlag()) return true;
        for (DiffNode child : this){
            if (child.getBuildFlagRecursive()) return true;
        }
        return false;
    }

	/**
	 *
	 * @param diff
	 */
	public void setDiffFlag(boolean diff){
        c_diffFlag = diff;
    }

	/**
	 *
	 * @return
	 */
	public boolean getDiffFlag(){
        return c_diffFlag;
    }

	/**
	 *
	 * @return
	 */
	public boolean getDiffFlagRecursive(){
        if (getDiffFlag()) return true;
        for (DiffNode child : this){
            if (child.getDiffFlagRecursive()) return true;
        }
        return false;
    }

	/**
	 *
	 * @param bit
	 * @return
	 */
	public boolean hasDiffFlag(int bit){
        return DiffEngine.bitFlag(c_diff, bit);
    }

	/**
	 *
	 * @param parent
	 */
	public void setParent(DiffNode parent){
        c_parent = parent;
    }

	/**
	 *
	 * @return
	 */
	public DiffNode getParent(){
        return c_parent;
    }

	/**
	 *
	 * @return
	 */
	public int getDepth(){
        if (getParent() == null) return 0;                  
        else return getParent().getDepth() + 1;
    }

	/**
	 *
	 * @param node
	 * @return
	 */
	public int indexOf(DiffNode node){
        return c_childNodes.indexOf(node);
    }
    

                    
}
