/*
   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/.

   Redistribution in source and binary forms, with or without modification, are not permitted.

   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 javax.swing.*;
import java.util.*;
import javax.swing.tree.*;


public class DeleteManager {
    
    private static boolean askForTaskDeletion() {
        if (Manager.currentComponent == null) {
            return false;
        }

        //shijian 2001-4-20 
        //Manager.resetPredecessorStore();
        //Manager.findPrecComs(Manager.currentComponent);
        //Manager.printPredecessors();
        
        //find successors
        //Manager.resetSuccessorStore();
        //Manager.findSuccComs(Manager.currentComponent);
        //Manager.printSuccessors();

        /*int choice;

        if (Manager.currentComponent instanceof Link) {
            String [] options = {"Delete the link","Cancel"};
            String newline = "\n";
            String message = "Are you sure that you want to delete the following link :"+newline+
                "\""+Manager.currentComponent.name+"\" ?";
            choice = JOptionPane.showOptionDialog(Manager.currentComponent.getParent(),
                message,
                "Link Deletion",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE,
                null,
                options,
                options[0]);
        } else {
            String [] options = {"Delete the task","Cancel"};
            String newline = "\n";
            String message = "Are you sure that you want to delete the following task :"+newline+
                "\""+Manager.currentComponent.name+"\" ?";
            choice = JOptionPane.showOptionDialog(Manager.currentComponent.getParent(),
                message,
                "Task Deletion",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE,
                null,
                options,
                options[0]);
        }
      
        if (choice == 0) {
            return true;
        }
        else {
            return false;
        }*/

        if (Manager.currentComponent instanceof Link) {
            return MessageDialog.askIfYesWithWarning(MainFrame.mainFrame,"Link Deletion",
                "Are you sure that you want to delete the following link : \n"+
                "\""+Manager.currentComponent.name+"\" ?",
                "Delete the link","Cancel");
        } else {
            return MessageDialog.askIfYesWithWarning(MainFrame.mainFrame,"Task Deletion",
                "Are you sure that you want to delete the following task : \n"+
                "\""+Manager.currentComponent.name+"\" ?",
                "Delete the task","Cancel");
        }
    }

    private static boolean askForMutlipleTaskDeletion() {
        return MessageDialog.askIfYesWithWarning(MainFrame.mainFrame,"Multiple Task Deletion",
            "Are you sure that you want to delete the following tasks / links ?\n\n"+
            BottomUp.constructNameList()+"\n",
            "Delete the tasks / links","Cancel");
    }
    
    private static boolean askForLinkDeletion(int numLinks) {
        String message = "This component has "+numLinks+" link"+
            ((numLinks>1)?"s.\nThey":".\nIt") +" will be removed with it.";
        
        return MessageDialog.askIfYesWithWarning(MainFrame.mainFrame,"Warning",
            message,"Ok","Cancel");
    }
    
    private static boolean askForMutlipleLinksDeletion(int numLinks) {
        String message = "The selected tasks have "+numLinks+" link"+
            ((numLinks>1)?"s.\nThey":".\nIt") +" will be removed!";
        
        return MessageDialog.askIfYesWithWarning(MainFrame.mainFrame,"Warning",
            message,"Ok","Cancel");
    }
    
    /**
     * Deletes a link from its parentNode + [skeleton] + [RTFDatabase] and from the tree
     */ 
    public static void deleteLink(Link link,String parentName) {
        if (link == null) return;

        String linkName = link.getName();
        Integer id2 = new Integer(link.ID);
        
        if (Manager.skeleton.isInTree(linkName)) {                
            Node parentNode = Manager.skeleton.toParentNode(linkName,parentName);

            // get treePath before any deletion takes place
            TreePath treePath = Manager.fetchTreePath(linkName,parentName,Manager.tree,id2);
                                           
            deleteLeaf(linkName,parentName,parentNode,id2);
            parentNode.removeCouple(linkName,id2);
            
            Manager.tree.removeInTree(treePath);

            //remove name for all other occurrences of parentName in tree
            Manager.tree.removeAllInTree(linkName,parentName);
        }
    }
    
    private static void deleteLeaf(String name,String parentName) {
        Manager.deleteFrame(name); //look if a frame of this name exist
        Manager.skeleton.removeFromRegister(name,parentName);
        
        if (!Manager.skeleton.isInRegister(name)) {
            //if (TMClipboard.isEmpty()) Manager.RTFDB.remove(name);
            //shijian 25-9-2001
            if (TMClipboard.isEmpty()) Manager.RTFDBM.remove(name);
           	else {
                Integer idClipboard = TMClipboard.getFirstID();
        
                //if (!name.equals(TMClipboard.getName(idClipboard))) Manager.RTFDB.remove(name);                
                //shijian 25-9-2001
                if (!name.equals(TMClipboard.getName(idClipboard))) Manager.RTFDBM.remove(name);
            }
        }
    }
    
    /**
     * Deletes a component from its frame, parentNode + [skeleton] + [RTFDatabase]
     */ 
    private static void deleteLeaf(String name,String parentName,Node parentNode,Integer id2) {
        Manager.deleteFrame(name); //look if a frame of this name exist
        
        //TMUtility.display("deleteLeaf : name",name);
        //TMUtility.display("deleteLeaf : parentName",parentName);
        //TMUtility.display("deleteLeaf : id2",id2);
        //TMUtility.displayLine(1);
        //parentNode.printNode();
        
        parentNode.removeCouple(name,id2);
        
        if (!parentNode.containsKey(name))
            Manager.skeleton.removeFromRegister(name,parentName);
        
        if (!Manager.skeleton.isInRegister(name)) {
            //if (TMClipboard.isEmpty()) Manager.RTFDB.remove(name);
            //shijian 25-9-2001
            if (TMClipboard.isEmpty()) Manager.RTFDBM.remove(name);
            else {
                Integer idClipboard = TMClipboard.getFirstID();
        
                //if (!name.equals(TMClipboard.getName(idClipboard))) Manager.RTFDB.remove(name);
                //shijian 25-9-2001
                if (!name.equals(TMClipboard.getName(idClipboard))) Manager.RTFDBM.remove(name);
            }
        }
    }

    private static void deleteSubComponentsInclusive(String name,String parentName,Integer id2) {
        Node[] parentNodeArray = Manager.skeleton.toChildNodes(parentName);
        
        for (int i = 0; i < parentNodeArray.length; i++) {
            Node parentNode = parentNodeArray[i];
            
            //TMUtility.display("deleteSubComponentsInclusive","parentNodeArray");
            //parentNode.printNode();
            
            deleteSubComponentsInclusive(name,parentName,parentNode,id2);
        }
    }
    
    //remove all sub-components of name (including name) :
    //  including [frame] + parentNode + [skeleton] + [RTFDatabase]
    private static void deleteSubComponentsInclusive(String name,String parentName,Node parentNode,Integer id2) {
        //TMUtility.display("deleteSubComponentsInclusive : name",name);
        //TMUtility.display("deleteSubComponentsInclusive : parentName",parentName);
        //TMUtility.display("deleteSubComponentsInclusive : id2",id2);
        //parentNode.printNode();
        //TMUtility.displayLine(1);
  
        if (parentNode.hasOtherDuplicatedTask(name)) {
            parentNode.removeCouple(name,id2);
            return;
        }
        
        if (parentNode.hasLeaf(name,id2)) {
            // delete leaf of name
            //JOptionPane.showMessageDialog(MainFrame.mainFrame,"delete leaf");
            deleteLeaf(name,parentName,parentNode,id2);
        }
        else {
            //delete branch of name
            if (Manager.skeleton.numOfParents(name) == 1) {
                // e.g. / -> A -> D -> E
                //        -> B -> D -> E
                // it should not delete D's node when B is to be deleted, resulting in / -> A -> D -> E
                // in this case : childName = E, name = D, currentNode = D's node
                Node currentNode = parentNode.getChild(name,id2);
                
                Set keys = currentNode.keySet();
                String [] childName = new String[keys.size()];
                
                int i = 0;
                for(Iterator it=keys.iterator();it.hasNext();)
                    childName[i++]=(String)(it.next());
                
                Integer childID;
                for (i=0;i<childName.length;i++) {
                    for (Iterator itID = currentNode.getIDIterator(childName[i]);itID.hasNext();) {
                        childID = (Integer) itID.next();
                        deleteSubComponentsInclusive(childName[i],name,currentNode,childID);
                    }
                }
            }
                
            // delete leaf of name
            deleteLeaf(name,parentName,parentNode,id2);
        }
    }
    
    private static int numLinkExisting(GenericComponent gc) {
        int result = 0;

        if (gc instanceof LinkableComponent) {
             LinkableComponent lc = (LinkableComponent) gc;
             result = lc.linkList.size();
        }
        
        return result;
    }
    
    private static void multipleDelete() {
        if (!askForMutlipleTaskDeletion()) return;
        
        int numLinks = BottomUp.numLinkExisting();
        if (numLinks > 0) {
            if (!askForMutlipleLinksDeletion(numLinks)) return;
        }
        
        // get the GenericComponent list
        GenericComponent [] gcList = BottomUp.getComponents();

        // delete the selected components
        for (int i=0; i<gcList.length; i++) {
            deleteGenericComponent(gcList[i]);
        }
        
        BottomUp.resetAllSelection();
    }
    
    /**
     * Delete recursively the selected component.
     */
    public static void delete() {
        if (BottomUp.isMultiComponentsSelected()) {
            multipleDelete();
            return;
        }
        
        if (!askForTaskDeletion()) return;
        
        if (Manager.currentComponent == null) return;

        int numLinks = numLinkExisting(Manager.currentComponent);
        if (numLinks > 0) {
            if (!askForLinkDeletion(numLinks)) return;
        }
        
        deleteGenericComponent(Manager.currentComponent);
    }
    
    private static void deleteLinks(LinkableComponent lc, String parentName) {
        Vector links = lc.getLinks();
        
        int size = links.size();
        
        //for (int i=0;i<size;i++){
        for (int i = size-1;i>=0;i--) {
            Link link = (Link) links.elementAt(i);
            lc.deleteLink(link);
            deleteLink(link,parentName);
        }
    }
    
    public static void deleteGenericComponent(GenericComponent gc) {
        if (gc == null) return;

        // get information about the component
        String name = gc.getName();
        Integer id2 = new Integer(gc.ID);
        
        //TMUtility.display("deleteGenericComponent : name",name);
        //TMUtility.display("deleteGenericComponent : id2",id2);
        
        String parentName = Manager.skeleton.getParent(name,id2);
        if (parentName == null) return;   // return if component deleted already
        
        Node parentNode = Manager.skeleton.toChildNode(parentName);
        
        TreePath treePath = Manager.fetchTreePath(name,parentName,Manager.tree);
        if (Manager.isRoot(treePath)) return;
        
        LinkableComponent lc2 = null;
        if (gc instanceof LinkableComponent) {
            // remove all links connected to the component
            deleteLinks((LinkableComponent) gc,parentName);
        }
        else {
            // get a component the link connecting to
            lc2 = ((Link) gc).getSecondLC();
        }

        // remove all sub-components of name (including name) : 
        //   including [frame] + parentNode + [skeleton] + [RTFDatabase]
        //deleteSubComponentsInclusive(name,parentName,parentNode,id2);
        deleteSubComponentsInclusive(name,parentName,id2);
           
        // if all components of parentName deleted, mark parentName as non-composite task
        if ((parentNode.isEmpty()) && (!(Manager.skeleton.isRoot(parentNode)))) {
             GenericComponent [] tab = Manager.skeleton.getComponents(parentName);
             for (int i=0;i<tab.length;i++)
                 if (tab[i] instanceof CompositeComponent)
                     ((CompositeComponent)tab[i]).setComposite(false);
        }

        // if the component is a link, delete the link
        if (!(gc instanceof LinkableComponent)) {
            if (lc2 != null) lc2.deleteLink((Link) gc);
        }

        // select the parent node in tree
        Manager.select(Manager.truncTreePath(treePath));

        // update tree to remove the component(s)
        Manager.tree.removeInTree(treePath);

        // remove name for all other occurrences of parentName in tree
        Manager.tree.synchronizeTreeStructure(Manager.truncTreePath(treePath));
        
        // redisplay the original parent frame --- corresponds to parentName
        Manager.updateParentFrame(treePath);
        
        // synchronize everything of the same duplicated tasks
        EditManager.restoreChildrenCoherence(name,parentName,id2,false);
        
        // mark parent task as dirty TRUE if it is not the root
        Manager.markTaskDirty(parentName,true);
        
        FileManager.MODIFIED=true;         
    }
    
    //tape_recorder
    public static void deleteGenericComponent(String name,String parentName) {
        GenericComponent gc = Manager.skeleton.getComponent(name,parentName);
        
        deleteGenericComponent(gc);
    }
}

