/*
   Tamot --- Task Modelling Editor
   Copyright (C) 2000 Commonwealth Scientific and Industrial Research Organisation
   (CSIRO), Australia. All rights reserved. 

   The Software, owned by CSIRO Australia, has been developed by the CSIRO 
   Intelligent Interactive Technology group. 
   For more information, please see http://www.cmis.csiro.au/iit/.

   The Software is a beta-test version for internal research and evaluation purposes 
   by the Licensee. The Software is still at a development stage. 
   It has not undergone complete testing and may have inherent errors,
   bugs or deficiencies that can affect the operation of the Software. 

   We encourage your feedback and suggestions. Any bugs / suggestions found please email to
   Shijian.Lu@cmis.csiro.au and Thomas.Lo@cmis.csiro.au. 

   After you have signed the Beta-Test Software License Agreement with the CSIRO,
   CSIRO grants you a non-exclusive, non-transferable license to use it only for your 
   personal, non-commercial and lawful end use. Implied licenses are negated. 

   Warranty Disclaimer : 

   CSIRO supplies the Software on an "as is" basis and makes no warranties that use of
   the Software by the Licensee will not infringe any third party’s 
   Intellectual Property Rights nor that the Software will be of merchantable quality,
   or suitable for a particular purpose. CSIRO excludes all terms, conditions and
   warranties implied by custom, the general law or statute in relation to the
   Software.
*/

package taskModellingTool;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.util.*;

public class ImprovedJTree extends JTree {
    
    protected static final String ROOT_STRING="/";
    private Graph kg;
    private DefaultMutableTreeNode jroot;
    private Node root;
    
    public DisplayedJTree displayTree;
    
    public ImprovedJTree() {
    	super(new DefaultMutableTreeNode(ROOT_STRING));
    	getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    	
    	//setCellRenderer(new ModifiedDefaultTreeCellRenderer());
    	
    	kg=null;
        
        displayTree = new DisplayedJTree();
    }
    
    //form similar tree structure of currentNode to jcurrent
    private void construction(Node currentNode,DefaultMutableTreeNode jcurrent) {
        DefaultMutableTreeNode jchild;
        String childName;
        Integer childID;
        boolean linkFlag, addInTreeFlag;
        
        if (!currentNode.isEmpty()) {
     	    for (Iterator i=(currentNode.keySet()).iterator();i.hasNext();) {
    	        childName = (String)(i.next());
    	        
	        	for (Iterator itID = currentNode.getIDIterator(childName);itID.hasNext();) {
   		    		childID = (Integer)(itID.next());
                    
                    addInTreeFlag = true;
                    if (!Manager.displayLinkInTreeEnableFlag) {
                        linkFlag = currentNode.isLink(childName,childID);
                        //System.out.println("childName = "+childName+", childID = "+childID+", linkFlag = "+linkFlag);
                        if (linkFlag) addInTreeFlag = false;
                    }
                     
                    //System.out.println("childName = "+childName+", childID = "+childID+", addInTreeFlag = "+addInTreeFlag);
                    
                    if (addInTreeFlag) {
                        jchild = new DefaultMutableTreeNode(childName);
                    
                        //if (!currentNode.hasLeaf(childName,childID)) 
                        //    construction(currentNode.getChild(childName,childID),jchild);
                        if (!currentNode.hasLeaf(childName))      // because duplicated tasks have the same decomposition
                            construction(currentNode.getChild(childName),jchild);
                        
                        jcurrent.add(jchild);
                    }
	        	}
    	    }
    	}
    }
    
    public void fill(Graph newkg) {
    	reset();
    	kg = newkg;
    	root = kg.getRoot();
	   	jroot = (DefaultMutableTreeNode)((DefaultTreeModel)getModel()).getRoot();
		construction(root,jroot);
        
        displayTree.fill(jroot);
    }
    
    public void reset() {
        setModel(new DefaultTreeModel(new DefaultMutableTreeNode(ROOT_STRING)));    	
        
        displayTree.reset();
    }

    public void removeInTree(TreePath treePath) {
    	DefaultMutableTreeNode node=(DefaultMutableTreeNode)(treePath.getLastPathComponent());
    	((DefaultTreeModel)getModel()).removeNodeFromParent(node);    	 
    }

    private void removeNameInChild(DefaultMutableTreeNode jcurrent,String name,String parentName) {
        for (Enumeration e = jcurrent.children();e.hasMoreElements();) {
        	DefaultMutableTreeNode jchild = (DefaultMutableTreeNode)e.nextElement();
 	        String childName = (String)jchild.getUserObject();
 	        
 	        if (childName.equals(name)) {
		    	((DefaultTreeModel)getModel()).removeNodeFromParent(jchild);    	 
 	        }
 	        else {
 	        	removeAllInTree(jchild,name,parentName);
 	        }
        }
    }
    
    private void removeAllInTree(DefaultMutableTreeNode jcurrent,String name,String parentName) {
        for (Enumeration e = jcurrent.children();e.hasMoreElements();) {
        	DefaultMutableTreeNode jchild = (DefaultMutableTreeNode)e.nextElement();
 	        String childName = (String)jchild.getUserObject();
 	        
 	        if (childName.equals(parentName)) {
 	        	removeNameInChild(jchild,name,parentName);
 	        }
 	        else {
 	        	removeAllInTree(jchild,name,parentName);
 	        }
        }
    }
    
    //remove name for all occurrences of parentName in tree
    public void removeAllInTree(String name,String parentName) {
    	DefaultMutableTreeNode jroot = 
    		(DefaultMutableTreeNode)((DefaultTreeModel)getModel()).getRoot();
    
    	removeAllInTree(jroot,name,parentName);
    }
    
    public void construction(DefaultMutableTreeNode jcopyFrom,DefaultMutableTreeNode jcopyTo) {
        for (Enumeration e = jcopyFrom.children();e.hasMoreElements();) {
        	DefaultMutableTreeNode jchild = (DefaultMutableTreeNode)e.nextElement();
        	
	    	String childName = (String)jchild.getUserObject();
	    	
	    	DefaultMutableTreeNode jclone = new DefaultMutableTreeNode(childName);
	    	
	    	if (!jchild.isLeaf())
	    		construction(jchild,jclone);

	    	jcopyTo.add(jclone);
        }
    }

    public void copyTreeStructure(DefaultMutableTreeNode jparent,DefaultMutableTreeNode jparent_template) {
    	if (jparent.equals(jparent_template)) return;

    	jparent.removeAllChildren();
    	
    	construction(jparent_template,jparent);
    	
    	((DefaultTreeModel)getModel()).reload(jparent);
    }
    
    public void synchronizeTreeStructure(DefaultMutableTreeNode jparent,DefaultMutableTreeNode jparent_template,
    	String parentName) {
    		
        for (Enumeration e = jparent.children();e.hasMoreElements();) {
        	DefaultMutableTreeNode jcurrent = (DefaultMutableTreeNode)e.nextElement();
 	        String name = (String)jcurrent.getUserObject();
 	        
 	        if (name.equals(parentName)) {
 	        	copyTreeStructure(jcurrent,jparent_template);
 	        }
 	        else {
 	        	synchronizeTreeStructure(jcurrent,jparent_template,parentName);
 	        }
        }
    }
    
    public void synchronizeTreeStructure(TreePath parentTreePath) {
    	DefaultMutableTreeNode jparent_template = (DefaultMutableTreeNode)(parentTreePath.getLastPathComponent());
    	if (jparent_template.isRoot()) return;
    	
        String parentName = (String)jparent_template.getUserObject();

    	DefaultMutableTreeNode jroot = 
    		(DefaultMutableTreeNode)((DefaultTreeModel)getModel()).getRoot();
    
    	synchronizeTreeStructure(jroot,jparent_template,parentName);
    }
    
    private void addInTree(DefaultMutableTreeNode jparent,String name) {
        DefaultMutableTreeNode jcurrent = new DefaultMutableTreeNode(name);
        ((DefaultTreeModel)getModel()).insertNodeInto(jcurrent,jparent,0);         
    }

    //append a DefaultMutableTreeNode name to parentTreePath
    public void addInTree(TreePath parentTreePath,String name) {
    	DefaultMutableTreeNode jcurrent = new DefaultMutableTreeNode(name);
    	DefaultMutableTreeNode jparent = (DefaultMutableTreeNode)(parentTreePath.getLastPathComponent());
    	((DefaultTreeModel)getModel()).insertNodeInto(jcurrent,jparent,0);    	 
    }

    public void addInTree(TreePath parentTreePath,String name,int index) {
    	if (index < 0) index = 0;
    	
    	DefaultMutableTreeNode jcurrent = new DefaultMutableTreeNode(name);
    	DefaultMutableTreeNode jparent = (DefaultMutableTreeNode)(parentTreePath.getLastPathComponent());
    	((DefaultTreeModel)getModel()).insertNodeInto(jcurrent,jparent,index);    	 
    }

    /*private void construction(Node current,DefaultMutableTreeNode jcurrent){
        DefaultMutableTreeNode jchild;
        String key;
        
        if (!current.isEmpty()){
     	    for (Iterator i=(current.getKeys()).iterator();i.hasNext();){
    	        key=(String)(i.next());
    	        jchild=new DefaultMutableTreeNode(key);
    	        if (!current.hasLeaf(key)) construction(current.getChild(key),jchild);
    	        jcurrent.add(jchild);
    	    }
    	}
    }*/
    
    public void synchronizeTree(String name,Node currentNode) {
        jroot = (DefaultMutableTreeNode) ((DefaultTreeModel)getModel()).getRoot();
        
        synchronizeTree(jroot,name,currentNode);
    }
        
    private void synchronizeTree(DefaultMutableTreeNode jcurrent,String name,Node currentNode) {
        for (Enumeration e = jcurrent.children(); e.hasMoreElements();) {
            DefaultMutableTreeNode jchild = (DefaultMutableTreeNode) e.nextElement();
            String childName = (String) jchild.getUserObject();
             
            if (childName.equals(name)) {
                ((DefaultTreeModel)getModel()).removeNodeFromParent(jchild);
                addRecursivelyInTree(jcurrent,name,currentNode);
            } else {
                synchronizeTree(jchild,name,currentNode);
            }
        }
    }

    private void addRecursivelyInTree(DefaultMutableTreeNode jparent,String name,Node currentNode) {
        if (currentNode==null) addInTree(jparent,name);
        else {
            DefaultMutableTreeNode jcurrent = new DefaultMutableTreeNode(name);
            
            //construct similar tree structure of currentNode to jcurrent
            construction(currentNode,jcurrent);
            
            ((DefaultTreeModel)getModel()).insertNodeInto(jcurrent,jparent,0);
        }         
    }

    //add name to parentTreePath as well as its tree structure similar to currentNode
    public void addRecursivelyInTree(TreePath parentTreePath,String name,Node currentNode) {
    	if (currentNode==null) addInTree(parentTreePath,name);
    	else {
    	    DefaultMutableTreeNode jcurrent = new DefaultMutableTreeNode(name);
    	    
    	    //construct similar tree structure of currentNode to jcurrent
    	    construction(currentNode,jcurrent);
    	    
    	    DefaultMutableTreeNode jparent = 
    	    	(DefaultMutableTreeNode)(parentTreePath.getLastPathComponent());
    	    	
    	    ((DefaultTreeModel)getModel()).insertNodeInto(jcurrent,jparent,0);
    	}    	 
    }

    public void addRecursivelyInTree(TreePath parentTreePath,String name,Node currentNode,int index) {
    	if (index < 0) index = 0;
    	
    	if (currentNode==null) addInTree(parentTreePath,name,index);
    	else {
    	    DefaultMutableTreeNode jcurrent = new DefaultMutableTreeNode(name);
    	    
    	    //construct similar tree structure of currentNode to jcurrent
    	    construction(currentNode,jcurrent);
    	    
    	    DefaultMutableTreeNode jparent = 
    	    	(DefaultMutableTreeNode)(parentTreePath.getLastPathComponent());
    	    	
    	    ((DefaultTreeModel)getModel()).insertNodeInto(jcurrent,jparent,index);
    	}    	 
    }
}