/*
   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 java.util.*;
import java.io.*;
import java.awt.*;


// manager of selecting & unselecting multiple components (tasks, boolean connectors) using Shift key
public class BottomUp {
    // include user-selected tasks, boolean connectors and links
    private static TreeMap shiftRegister = new TreeMap();  // id2 (key), gc (value)
    
    public static String lastParentName = null;

    // include links of the selected components (tasks + boolean connectors)
    //   : may / may not include the user-selected links
    private static TreeMap linkRegister = new TreeMap();  // id2 (key), link (value)
    
    // include links of the selected components (tasks + boolean connectors) 
    // that are to be retained in the clipboard after cut / copy
    //   : may / may not include the user-selected links
    private static TreeMap linkRetainedRegister = new TreeMap();  // id2 (key), link (value)
    
    // include the selected components (tasks + boolean connectors)
    private static TreeMap linkableComponentRegister = new TreeMap();  // id2 (key), lc (value)
    
    public static final Color BACKGROUND_SHIFT_SELECTED_COLOR = new Color(250,250,0);
    
    
    public static boolean isComponentExistInShiftRegister(GenericComponent gc) {
        boolean result = false;
        
        if (gc == null) return result;
        
        Integer id2 = new Integer(gc.ID);

        if (shiftRegister.containsKey(id2)) result = true;
        
        return result;
    }
    
    public static boolean isComponentExistInShiftRegister(Component c) {
        boolean result = false;
    
        if (c instanceof GenericComponent) {
            GenericComponent gc = (GenericComponent) c;
            result = isComponentExistInShiftRegister(gc);
        }
        
        return result;
    }
    
    public static boolean isComponentExistInShiftRegister(LinkableComponent lc1) {
        boolean result = false;
        
        if (lc1 == null) return result;
        
        Integer id2 = new Integer(lc1.ID);

        if (shiftRegister.containsKey(id2)) result = true;
        
        return result;
    }

    private static boolean isLinkExistInLinkRetainedRegister(Link link) {
        boolean result = false;
        
        if (link == null) return result;
        
        Integer id2 = new Integer(link.ID);

        if (linkRetainedRegister.containsKey(id2)) result = true;
        
        return result;
    }

    private static void addToShiftRegister(GenericComponent gc) {
        if (gc == null) return;
        
        Integer id2 = new Integer(gc.ID);
        shiftRegister.put(id2,gc);
    }
    
    private static void removeFromShiftRegister(GenericComponent gc) {
        if (gc == null) return;
        
        Integer id2 = new Integer(gc.ID);
        shiftRegister.remove(id2);
    }
    
    public static void toggleSelect(GenericComponent gc, String parentName) {
        if (gc == null) return;
        if (parentName == null) return;
        
        //TMUtility.display("toggleSelect : parentName",parentName);
        
        if ( (lastParentName == null) || (!lastParentName.equals(parentName)) ) {
            resetAllSelection();
            lastParentName = parentName;
        }
        
        if (isComponentExistInShiftRegister(gc)) {
            removeFromShiftRegister(gc);
            gc.setShiftSelected(false);
        }
        else {
            addToShiftRegister(gc);
            gc.setShiftSelected(true);
        }
        
        gc.repaint();
    }
    
    public static void select(GenericComponent gc, String parentName) {
        if (gc == null) return;
        if (parentName == null) return;
        
        if ( (lastParentName == null) || (!lastParentName.equals(parentName)) ) {
            resetAllSelection();
            lastParentName = parentName;
        }
        
        if (!isComponentExistInShiftRegister(gc)) {
            addToShiftRegister(gc);
            gc.setShiftSelected(true);
            gc.repaint();
        }
    }
    
    public static void unselect(GenericComponent gc, String parentName) {
        if (gc == null) return;
        if (parentName == null) return;
        
        if ( (lastParentName == null) || (!lastParentName.equals(parentName)) ) {
            resetAllSelection();
            lastParentName = parentName;
        }
        
        if (isComponentExistInShiftRegister(gc)) {
            removeFromShiftRegister(gc);
            gc.setShiftSelected(false);
            gc.repaint();
        }
    }
 
    public static void setParent(String parentName) {
        lastParentName = parentName;
    }
    
    public static void resetAllSelection() {
        //TMUtility.display("resetAllSelection","");
        
        Set keys = shiftRegister.keySet();
        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            
            GenericComponent gc = (GenericComponent) shiftRegister.get(id2);

            if (gc != null) {
                gc.setShiftSelected(false);
                gc.repaint();
            }
        }

        shiftRegister.clear();
        lastParentName = null;
        
        linkRegister.clear();
        linkRetainedRegister.clear();
        linkableComponentRegister.clear();
        
        MultipleComponents.reset();
    }
    
    public static boolean isParentChanged(String name) {
        boolean result = true;
        
        if (name.equals(lastParentName)) result = false;
        
        return result;
    }
    
    public static boolean isMultiComponentsSelected() {
        boolean result = false;
        
        Set keys = shiftRegister.keySet();
        
        if (keys.size() > 0) result = true;
        
        return result;
    }
    
    public static String constructNameList() {
        StringBuffer result = new StringBuffer();
        
        Set keys = shiftRegister.keySet();

        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            
            GenericComponent gc = (GenericComponent) shiftRegister.get(id2);
            
            result.append("\""+gc.getName()+"\"\n");
        }
        
        return result.toString();
    }

    private static int getNumGenericComponents() {
        Set keys = shiftRegister.keySet();

        return (keys.size());
    }
    
    public static GenericComponent [] getComponents() {
        GenericComponent [] result = null;
        
        result = new GenericComponent[getNumGenericComponents()];
        
        //fill array of GenericComponent
        Set keys = shiftRegister.keySet();

        int index = 0;
        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            GenericComponent gc = (GenericComponent) shiftRegister.get(id2);
            
            //TMUtility.display("BottomUp.getComponents()",gc.getName());

            result[index++] = gc;
        }
        
        return result;
    }
    
    private static int getNumLinkableComponents() {
        Set keys = linkableComponentRegister.keySet();

        return (keys.size());
    }
    
    public static LinkableComponent [] getLinkableComponents() {
        LinkableComponent [] result = null;
        
        result = new LinkableComponent[getNumLinkableComponents()];
        
        //fill array of LinkableComponent
        Set keys = linkableComponentRegister.keySet();

        int index = 0;
        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            LinkableComponent lc = (LinkableComponent) linkableComponentRegister.get(id2);
            
            //TMUtility.display("BottomUp.getLinkableComponents()",lc.getName());

            result[index++] = lc;
        }
        
        return result;
    }
   
    private static int getNumLinks() {
        Set keys = linkRetainedRegister.keySet();

        return (keys.size());
    }
    
    public static Link [] getLinks() {
        Link [] result = null;
        
        result = new Link[getNumLinks()];
        
        //fill array of Link
        Set keys = linkRetainedRegister.keySet();

        int index = 0;
        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            Link link = (Link) linkRetainedRegister.get(id2);
            
            //TMUtility.display("BottomUp.getLinks()",link.getName());
            //TMUtility.display("    id2",id2);

            result[index++] = link;
        }
        
        return result;
    }
    
    public static Link [] getExcludedLinks() {
        Link [] result = null;
        
        Set keys = linkRegister.keySet();
        Set keys2 = linkRetainedRegister.keySet();

        result = new Link[keys.size() - keys2.size()];
        
        int index = 0;
        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            Link link = (Link) linkRegister.get(id2);
            
            if (!isLinkExistInLinkRetainedRegister(link)) {
                result[index++] = link;
            }
        }
        
        return result;
    }
   
    private static void addToLinkRegister(Link link) {
        if (link == null) return;
        
        Integer id2 = new Integer(link.ID);
        linkRegister.put(id2,link);

        //TMUtility.display("BottomUp.addToLinkRegister()",link.getName());
    }
    
    private static void addToLinkRetainedRegister(Link link) {
        if (link == null) return;
        
        Integer id2 = new Integer(link.ID);
        linkRetainedRegister.put(id2,link);

        //TMUtility.display("BottomUp.addToLinkRetainedRegister()",link.getName());
    }
    
    private static void updateLinkRetainedRegister() {
        linkRetainedRegister.clear();

        Set keys = linkRegister.keySet();
        //TMUtility.display("BottomUp.updateLinkRetainedRegister : size",keys.size());

        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            Link link = (Link) linkRegister.get(id2);

            //TMUtility.display("BottomUp.updateLinkRetainedRegister()",link.getName());
            //TMUtility.display("    lc1",link.lc1.getName());
            //TMUtility.display("    lc2",link.lc2.getName());
            
            if (isComponentExistInShiftRegister(link.lc1)) {
                if (isComponentExistInShiftRegister(link.lc2))
                    addToLinkRetainedRegister(link);
            }
        }
    }
    
    private static void updateLinkRegister() {
        linkRegister.clear();

        Set keys = shiftRegister.keySet();

        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            GenericComponent gc = (GenericComponent) shiftRegister.get(id2);
            
            if (gc instanceof LinkableComponent) {
                LinkableComponent lc = (LinkableComponent) gc;
                Vector links = lc.getLinks();
                
                int size = links.size();
                for (int i = size-1;i>=0;i--) {
                    Link link = (Link) links.elementAt(i);
                    addToLinkRegister(link);
                }
            }
        }
    }
    
    public static int numLinkExisting() {
        updateLinkRegister();
        
        Set keys = linkRegister.keySet();

        int result = keys.size();

        //TMUtility.display("BottomUp.numLinkExisting()",result);
        
        return result;
    }

    private static void addToLinkableComponentRegister(LinkableComponent lc) {
        if (lc == null) return;
        
        Integer id2 = new Integer(lc.ID);
        linkableComponentRegister.put(id2,lc);

        //TMUtility.display("BottomUp.addToLinkableComponentRegister()",lc.getName());
    }
    
    public static void updateLinkableComponentRegister() {
        linkableComponentRegister.clear();
        
        Set keys = shiftRegister.keySet();

        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            GenericComponent gc = (GenericComponent) shiftRegister.get(id2);
            
            if (gc instanceof LinkableComponent) {
                LinkableComponent lc = (LinkableComponent) gc;
                addToLinkableComponentRegister(lc);
            }
        }
    }

    public static boolean isLinksOnly() {
        updateLinkableComponentRegister();
        
        Set keys = linkableComponentRegister.keySet();

        int num = keys.size();
        
        if (num == 0) return true;
        else return false;
    }

    public static void updateRegisters() {
        updateLinkRegister();
        updateLinkRetainedRegister();
    }
    
    public static int numLinkExcluded() {
        updateRegisters();
        
        Set keys1 = linkRegister.keySet();
        Set keys2 = linkRetainedRegister.keySet();

        int result = keys1.size() - keys2.size();

        //TMUtility.display("BottomUp.numLinkExcluded()",result);
        
        return result;
    }
    
    public static void updateLinksDisplay() {
        Set keys = linkRegister.keySet();

        for (Iterator it = keys.iterator();it.hasNext();) {
            Integer id2 = (Integer) it.next();
            Link link = (Link) linkRegister.get(id2);

            if (isLinkExistInLinkRetainedRegister(link))
                select(link,lastParentName);
            else
                unselect(link,lastParentName);
        }
    }
}