/*******************************************************************************
 * Copyright (c) 2004, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.dnd;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.util.Geometry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tracker;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.DragCursors;

/**
 * Provides the methods for attaching drag-and-drop listeners to SWT controls. 
 */
public class DragUtil {
    private static final String DROP_TARGET_ID = "org.eclipse.ui.internal.dnd.dropTarget"; //$NON-NLS-1$

    /**
     * The location where all drags will end. If this is non-null, then
     * all user input is ignored in drag/drop. If null, we use user input
     * to determine where objects should be dropped.
     */
    private static TestDropLocation forcedDropTarget = null;
    
    /**
     * List of IDragOverListener
     */
    private static List defaultTargets = new ArrayList();

    /**
     * Sets the drop target for the given control. It is possible to add one or more 
     * targets for a "null" control. This becomes a default target that is used if no
     * other targets are found (for example, when dragging objects off the application
     * window). 
     * 
     * @param control the control that should be treated as a drag target, or null
     * to indicate the default target
     * @param target the drag target to handle the given control
     */
    public static void addDragTarget(Control control, IDragOverListener target) {
        if (control == null) {
            defaultTargets.add(target);
        } else {
            List targetList = getTargetList(control);

            if (targetList == null) {
                targetList = new ArrayList(1);
            }
            targetList.add(target);
            control.setData(DROP_TARGET_ID, targetList);
        }
    }

    /**
     * Return the list of 'IDragOverListener' elements associated with
     * the given control. If there's a 'global' listener then always
     * return it.
     * 
     * @param control
     * @return
     */
    private static List getTargetList(Control control) {
        List result = (List) control.getData(DROP_TARGET_ID);
        return result;
    }

    /**
     * Removes a drop target from the given control.
     * 
     * @param control
     * @param target
     */
    public static void removeDragTarget(Control control,
            IDragOverListener target) {
        if (control == null) {
            defaultTargets.remove(target);
        } else {
            List targetList = getTargetList(control);
            if (targetList != null) {
                targetList.remove(target);
                if (targetList.isEmpty()) {
                    control.setData(DROP_TARGET_ID, null);
                }
            }
        }
    }

    /**
     * Shorthand method. Returns the bounding rectangle for the given control, in
     * display coordinates. Note that all 'Shell' controls are expected to be 'top level'
     * so DO NOT do the origin offset for them.
     * 
     * @param draggedItem
     * @param boundsControl
     * @return
     */
    public static Rectangle getDisplayBounds(Control boundsControl) {
        Control parent = boundsControl.getParent();
        if (parent == null || boundsControl instanceof Shell) {
            return boundsControl.getBounds();
        }

        return Geometry.toDisplay(parent, boundsControl.getBounds());
    }

    public static boolean performDrag(final Object draggedItem,
            Rectangle sourceBounds) {
        return performDrag(draggedItem, sourceBounds, Display.getDefault()
                .getCursorLocation(), false);
    }

    public static boolean performDrag(final Object draggedItem,
            Rectangle sourceBounds, Point initialLocation, boolean allowSnapping) {

        IDropTarget target = dragToTarget(draggedItem, sourceBounds,
                initialLocation, allowSnapping);

        if (target == null) {
            return false;
        }

        target.drop();

        // If the target can handle a 'finished' notification then send one
        if (target!= null && target instanceof IDropTarget2) {
        	((IDropTarget2)target).dragFinished(true);
        }

        return true;
    }

    /**
     * Drags the given item to the given location (in display coordinates). This
     * method is intended for use by test suites.
     * 
     * @param draggedItem object being dragged
     * @param finalLocation location being dragged to
     * @return true iff the drop was accepted
     */
    public static boolean dragTo(Display display, Object draggedItem,
            Point finalLocation, Rectangle dragRectangle) {
        Control currentControl = SwtUtil.findControl(display, finalLocation);

        IDropTarget target = getDropTarget(currentControl, draggedItem,
                finalLocation, dragRectangle);

        if (target == null) {
            return false;
        }

        target.drop();

        return true;
    }

    /**
     * Forces all drags to end at the given position (display coordinates). Intended
     * for use by test suites. If this method is called, then all subsequent calls
     * to performDrag will terminate immediately and behave as though the object were
     * dragged to the given location. Calling this method with null cancels this 
     * behavior and causes performDrag to behave normally. 
     * 
     * @param forcedLocation location where objects will be dropped (or null to
     * cause drag/drop to behave normally).
     */
    public static void forceDropLocation(TestDropLocation forcedLocation) {
        forcedDropTarget = forcedLocation;
    }
    
    /**
     * Drags the given item, given an initial bounding rectangle in display coordinates.
     * Due to a quirk in the Tracker class, changing the tracking rectangle when using the
     * keyboard will also cause the mouse cursor to move. Since "snapping" causes the tracking
     * rectangle to change based on the position of the mouse cursor, it is impossible to do
     * drag-and-drop with the keyboard when snapping is enabled.    
     * 
     * @param draggedItem object being dragged
     * @param sourceBounds initial bounding rectangle for the dragged item
     * @param initialLocation initial position of the mouse cursor
     * @param allowSnapping true iff the rectangle should snap to the drop location. This must
     * be false if the user might be doing drag-and-drop using the keyboard. 
     *  
     * @return
     */
    static IDropTarget dragToTarget(final Object draggedItem,
            final Rectangle sourceBounds, final Point initialLocation,
            final boolean allowSnapping) {
        final Display display = Display.getCurrent();

        // Testing...immediately 'drop' onto the test target
        if (forcedDropTarget != null) {
            Point location = forcedDropTarget.getLocation();

            Control currentControl = SwtUtil.findControl(forcedDropTarget.getShells(), location);
            return getDropTarget(currentControl, draggedItem, location,
                    sourceBounds);
        }

        // Create a tracker.  This is just an XOR rect on the screen.
        // As it moves we notify the drag listeners.
        final Tracker tracker = new Tracker(display, SWT.NULL);
        tracker.setStippled(true);

        tracker.addListener(SWT.Move, new Listener() {
            public void handleEvent(final Event event) {
                display.syncExec(new Runnable() {
                    public void run() {
                    	// Get the curslor location as a point
                        Point location = new Point(event.x, event.y);

                        // Select a drop target; use the global one by default
                    	IDropTarget target = null;
                    		
                        Control targetControl = display.getCursorControl();

                        // Get the drop target for this location
                        target = getDropTarget(targetControl,
                                draggedItem, location,
                                tracker.getRectangles()[0]);

                    	// Set up the tracker feedback based on the target
                        Rectangle snapTarget = null;
                        if (target != null) {
                            snapTarget = target.getSnapRectangle();

                            tracker.setCursor(target.getCursor());
                        } else {
                            tracker.setCursor(DragCursors
                                    .getCursor(DragCursors.INVALID));
                        }

                        // If snapping then reset the tracker's rectangle based on the current drop target 
                        if (allowSnapping) {
                            if (snapTarget == null) {
                                snapTarget = new Rectangle(sourceBounds.x
                                        + location.x - initialLocation.x,
                                        sourceBounds.y + location.y
                                                - initialLocation.y,
                                        sourceBounds.width, sourceBounds.height);
                            }

                            // Try to prevent flicker: don't change the rectangles if they're already in
                            // the right location
                            Rectangle[] currentRectangles = tracker.getRectangles();

                            if (!(currentRectangles.length == 1 && currentRectangles[0]
                                    .equals(snapTarget))) {
                                tracker.setRectangles(new Rectangle[] { snapTarget });
                            }
                        }
                    }
                });
            }
        });

        // Setup...when the drag starts we might already be over a valid target, check this...
        // If there is a 'global' target then skip the check
        IDropTarget target = null;
        Control startControl = display.getCursorControl();
        
        if (startControl != null && allowSnapping) {
            target = getDropTarget(startControl,
                draggedItem, initialLocation,
                sourceBounds);
        }

        // Set up an initial tracker rectangle
        Rectangle startRect = sourceBounds;
        if (target != null) {
            Rectangle rect = target.getSnapRectangle();
            
            if (rect != null) {
                startRect = rect;
            }

            tracker.setCursor(target.getCursor());
        } 
        
        if (startRect != null) {
            tracker.setRectangles(new Rectangle[] { Geometry.copy(startRect)});
        }

        // Tracking Loop...tracking is preformed on the 'SWT.Move' listener registered
        // against the tracker.
        
        // HACK:
        // Some control needs to capture the mouse during the drag or other 
        // controls will interfere with the cursor
        Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
        if (shell != null) {
            shell.setCapture(true);
        }

        // Run tracker until mouse up occurs or escape key pressed.
        boolean trackingOk = tracker.open();

        // HACK:
        // Release the mouse now
        if (shell != null) {
            shell.setCapture(false);
        }

        // Done tracking...
        
        // Get the current drop target
        IDropTarget dropTarget = null;
        Point finalLocation = display.getCursorLocation();
        Control targetControl = display.getCursorControl();
        dropTarget = getDropTarget(targetControl, draggedItem,
                finalLocation, tracker.getRectangles()[0]);

        // Cleanup...
        tracker.dispose();
        
        // if we're going to perform a 'drop' then delay the issuing of the 'finished'
        // callback until after it's done...
        if (trackingOk) {
        	return dropTarget;
        }
        else if (dropTarget!= null && dropTarget instanceof IDropTarget2) {
            // If the target can handle a 'finished' notification then send one
        	((IDropTarget2)dropTarget).dragFinished(false);
        }
        
        return null;
    }
    
    /**
     * Given a list of IDragOverListeners and a description of what is being dragged, it returns
     * a IDropTarget for the current drop.
     * 
     * @param toSearch
     * @param mostSpecificControl
     * @param draggedObject
     * @param position
     * @param dragRectangle
     * @return
     */
    private static IDropTarget getDropTarget(List toSearch,
            Control mostSpecificControl, Object draggedObject, Point position,
            Rectangle dragRectangle) {
        if (toSearch == null) {
            return null;
        }

        Iterator iter = toSearch.iterator();
        while (iter.hasNext()) {
            IDragOverListener next = (IDragOverListener) iter.next();

            IDropTarget dropTarget = next.drag(mostSpecificControl,
                    draggedObject, position, dragRectangle);

            if (dropTarget != null) {
                return dropTarget;
            }
        }

        return null;
    }

    /**
     * Returns the drag target for the given control or null if none. 
     * 
     * @param toSearch
     * @param e
     * @return
     */
    public static IDropTarget getDropTarget(Control toSearch,
            Object draggedObject, Point position, Rectangle dragRectangle) {
    	// Search for a listener by walking the control's parent hierarchy
        for (Control current = toSearch; current != null; current = current
                .getParent()) {
            IDropTarget dropTarget = getDropTarget(getTargetList(current),
                    toSearch, draggedObject, position, dragRectangle);

            if (dropTarget != null) {
                return dropTarget;
            }

            // Don't look to parent shells for drop targets
            if (current instanceof Shell) {
                break;
            }
        }

        // No controls could handle this event -- check for default targets
        return getDropTarget(defaultTargets, toSearch, draggedObject, position,
                dragRectangle);
    }

    /**
     * Returns the location of the given event, in display coordinates
     * @return
     */
    public static Point getEventLoc(Event event) {
        Control ctrl = (Control) event.widget;
        return ctrl.toDisplay(new Point(event.x, event.y));
    }

}
