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

package usda.weru.util.diff.table;

import com.klg.jclass.table.data.AbstractDataSource;
import java.util.List;
import java.util.Vector;
import usda.weru.util.diff.*;

/**
 *
 * @author Joseph Levin
 */
public class DiffTabelModel extends AbstractDataSource{
    private static final long serialVersionUID = 01L;
    private transient DiffNode c_rootNode;
    private List <DiffNode> c_data;
    private final String[] c_columnLabels = {"Parameter", "Diff", "A", "B"};
    /**
     * Creates a new instance of DiffTabelModel
     */
    public DiffTabelModel() {
        rebuild();
    }

	/**
	 *
	 */
	public void rebuild(){
        c_data = new Vector <DiffNode> ();
        if (c_rootNode == null) return;
        for (DiffNode child : c_rootNode){
            rebuild(child);
        }
        fireDataReset();
    }
    
    private void rebuild(DiffNode node){
        if (node == null) return;  
        c_data.add(node);
        for (DiffNode child : node){
            rebuild(child);
        }
    }

	/**
	 *
	 * @param node
	 */
	public void setRootNode(DiffNode node){
        if (node == c_rootNode) return;
        c_rootNode = node;
        rebuild();
    }
    
    //|Diff  | Tree/Parameter | A         | B         
    @Override
    public int getNumColumns(){
        return 4;
    }
    
    @Override
    public int getNumRows(){
        return c_data.size();
    }

	/**
	 *
	 * @param rowIndex
	 * @return
	 */
	public int getNumDescendants(int rowIndex){
        DiffNode node = c_data.get(rowIndex);
        return node.getChildCountRecursive();
    }

	/**
	 *
	 * @param rowIndex
	 * @return
	 */
	public int[] getDirectChildren(int rowIndex){
        DiffNode node = c_data.get(rowIndex);
        int[] directChildren = new int[node.getChildCount()];
        int i = 0;
        for (DiffNode child : node){
            directChildren[i] = c_data.indexOf(child);
            i++;
        }
        return directChildren;                
    }

	/**
	 *
	 * @param rowIndex
	 * @return
	 */
	public int getParentIndex(int rowIndex){
        DiffNode node = c_data.get(rowIndex);
        DiffNode parent = node.getParent();
        if (parent == null){
            return -1;
        }
        else{
            return c_data.indexOf(parent);
        }
    }
    
    @Override
    public Object getTableColumnLabel(int columnIndex){
        if (columnIndex < 0) return null;
        else return c_columnLabels[columnIndex];
    }
    
    @Override
    public Object getTableDataItem(int rowIndex, int columnIndex){
        DiffNode node = c_data.get(rowIndex);
        switch(columnIndex){
            case 0:
                return new TreeWrapper(rowIndex, node); 
            case 1:
                return new DiffWrapper(rowIndex, node);                 
            case 2:
                return node.getA();
            case 3:
                return node.getB();
        }
        return null;
    }
    
    @Override
    public Object getTableRowLabel(int rowIndex){
        return rowIndex;
    }
    
    
    private void addNode(DiffNode node){        
        //Stop if the node is already in the data list.
        if (c_data.contains(node)) return;
        
        //Stop if the node is null.
        if (node == null) return;
        
        DiffNode parent = node.getParent();
        //Stop if the top (blank) node of the diff tree;
        if (parent == null){
            c_data.add(node);
            fireRowsAdded(0, 1);
        }

        //Is the parent in the data?        
        if (!c_data.contains(parent)){
            addNode(parent);
        }
        else{
            int parentIndex = c_data.indexOf(parent);
            int offset = parent.indexOf(node); 
            c_data.add(parentIndex + offset, node);
            fireRowsAdded(parentIndex + offset, 1);
        }
        
        for (DiffNode child : node){
            addNode(child);
        }
    }
    
    private void replaceNode(DiffNode replace, DiffNode node){
        int index = c_data.indexOf(replace);
        c_data.set(index, node);
        fireRowChanged(index);
    }
    

        
}
