/*
   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.*;
import java.awt.Dimension;
import java.awt.Point;


// ADD LEVEL
public class PromoteManager {
    
    public static void promote() {
        // if not multiple components selected, select the current component in BottomUp
        includeSingleTaskInBottomUp();
        
        // if no component selected, give error message
        if (!BottomUp.isMultiComponentsSelected()) {
            MessageDialog.errorDialog(MainFrame.mainFrame,"Operation not allowed",
                "At least one component needs to be selected.");
            
            return;
        }
        
        if (!pointToParentTask()) return;
        
        // add the newly created task to the parent task
        //   the new task contains the multiple components as its decomposition
        //   ask the attributes of the new task
        Task newTask = NewManager.newTaskWithoutDuplicatedName();
        
        if (newTask == null) return;
        
        //TMUtility.display("promote","after newTask");

        String parentName = BottomUp.lastParentName;
        
        SourceDestinationManager.findSourceAndDestinationComponentsForPromote();
        
        Point middlePointOfSelectedComponents = 
            SourceDestinationManager.findMiddlePointInDecomposition();
        
        // cut multiple components selected to clipboard
        if (!CutManager.multipleCut(false)) return;
        
        if (TMClipboard.isEmpty()) return;
        
        //Manager.skeleton.printRegister();
        
        adjustTaskPosition(newTask,parentName,middlePointOfSelectedComponents);
        
        if (!isTaskHasDecomposition(newTask)) {
            // paste from the clipboard to the decomposition of the newly created task
            pasteClipboardToTaskDecomposition(newTask);
            
            SourceDestinationManager.joinSourceAndDestinationLinksIfOK(newTask,parentName);
        }
    }
    
    private static void includeSingleTaskInBottomUp() {
        if (BottomUp.isMultiComponentsSelected()) return;
        
        if (Manager.currentComponent == null) {
            //TMUtility.display("includeSingleTaskInBottomUp","Task not selected !");
            return;
        }
        
        GenericComponent gc = Manager.currentComponent;
        
        Integer id2 = new Integer(gc.ID);
        String name = gc.getName();
        
        String parentName = Manager.skeleton.getParent(name,id2);
        
        BottomUp.resetAllSelection();
        
        BottomUp.select(gc,parentName);
    }
    
    private static boolean isTaskHasDecomposition(Task newTask) {
        String name = newTask.getName();
        Integer id2 = new Integer(newTask.ID);
        
        boolean hasChildFlag = Manager.skeleton.hasChildNode(name,id2);
        
        //TMUtility.display("testIfTaskHasDecomposition : hasChildFlag",hasChildFlag);
        
        return hasChildFlag;
    }

    // adjust the position of the new task to be between the source and the destination tasks
    // if the position is originally empty
    private static void adjustTaskPosition(Task newTask, String parentName, 
        Point middlePointOfSelectedComponents) {
        
        // find the middle point between the source and the destination tasks
        Point middlePoint = new Point();
        
        if (!SourceDestinationManager.isFindPositionOK(middlePoint)) {
            // try to put the newTask in the middle of the cut components if not obstructed
            middlePoint = middlePointOfSelectedComponents;
            
            //return;
        }
        
        int backupX = newTask.getX();
        int backupY = newTask.getY();
        
        // put the newTask whose middle is at the middlePoint
        Point topLeftPoint = new Point();
        
        final int MIN_OFFSET = 10;  // minimum offset from the left-edge & the top-edge of the window
        
        // newTask.getX() + newTask.getWidth() / 2 = middlePoint.getX();
        double x = middlePoint.getX() - newTask.getWidth() / 2;
        //TMUtility.display("adjustTaskPosition : x",x);
        if (x < MIN_OFFSET) x = MIN_OFFSET;
        
        // newTask.getY() + newTask.getHeight() / 2 = middlePoint.getY();
        double y = middlePoint.getY() - newTask.getHeight() / 2;
        //TMUtility.display("adjustTaskPosition : y",y);
        if (y < MIN_OFFSET) y = MIN_OFFSET;
        
        topLeftPoint.setLocation(x,y);
        
        setTaskLocation(newTask,topLeftPoint);
        
        // if the new position intersects with the other component,
        // restore the newTask to its old position
        ComponentInternalFrame frame = (ComponentInternalFrame) Manager.desktop.fetchFrame(parentName);
        if (frame == null) return;
        if (frame.gpanel == null) return;
        
        if (MultipleComponents.intersection(newTask,frame.gpanel)) {
            //TMUtility.display("adjustTaskPosition","intersected --- restored to original position.");
            setTaskLocation(newTask,backupX,backupY);
        }
    }

    private static void setTaskLocation(Task newTask, Point topLeftPoint) {
        newTask.setLocation(topLeftPoint);
        
        newTask.backupX = newTask.getX();
        newTask.backupY = newTask.getY();
    }
    
    private static void setTaskLocation(Task newTask, int backupX, int backupY) {
        newTask.setLocation(backupX,backupY);
        
        newTask.backupX = newTask.getX();
        newTask.backupY = newTask.getY();
    }
    
    public static boolean pointToParentTask() {
        boolean result = false;
        
        TreePath treePath = Manager.tree.getSelectionPath();
        
        if (treePath == null) return result;
        
        String name = Manager.treePathToString(treePath);
        String parentName;
        
        result = (name.equals(Manager.ROOT_STRING));
        if (!result) {
            parentName = Manager.treePathToString(Manager.truncTreePath(treePath));
            GenericComponent gc = Manager.skeleton.stringToGenericComponent(name,parentName);
            if (gc instanceof CompositeComponent) {
                result = true ;
            
                Integer id2 = new Integer(gc.ID);
                Manager.select(gc,Manager.truncTreePath(treePath),id2);
            }
        }
        else
            parentName = Manager.skeleton.ROOT_STRING;
            
        if (result) {
            //TMUtility.display("pointToParentTask : name",name);
            //TMUtility.display("pointToParentTask : parentName",parentName);
        }
        
        return result;
    }
    
    private static void pasteClipboardToTaskDecomposition(Task newTask) {
        // get information to prepare for the promotion
        String name = newTask.getName();
        Integer id2 = new Integer(newTask.ID);
        
        String parentName = Manager.skeleton.getParent(name,id2);
        
        TreePath treePath = Manager.fetchTreePath(name,parentName,Manager.tree,id2);
        
        //TMUtility.display("pasteClipboardToTaskDecomposition : name",name);
        //TMUtility.display("pasteClipboardToTaskDecomposition : parentName",parentName);
        
        PasteManager.multiplePaste(10,10,true,treePath,name,parentName);
    }

}