/*
* Copyright (c) 2002 IBM Corporation and others.
* All rights reserved.   This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
* 
* Contributors:
*   IBM - Initial API and implementation
*   Jens Lukowski/Innoopract - initial renaming/restructuring
* 
*/
package org.eclipse.wst.common.ui.dnd;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;

import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.custom.TableTreeItem;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;


/**
 * This implementation of a drop target listener 
 * is designed to turn a drag and drop operation into a {@link Command} based on the model objects of an {@link EditingDomain}
 * and created by {@link DragAndDropManager#create}.
 * It is designed to do early data transfer so the the enablement and feedback of the drag and drop interaction
 * can intimately depend on the state of the model objects involed.
 * <p>
 * The base implementation of this class should be sufficient for most applications.
 * Any change in behaviour is typically accomplished by overriding 
 * {@link ItemProviderAdapter}.createDragAndDropCommand
 * to return a derived implementation of {@link DragAndDropCommand}.
 * This is how one these adapters is typically hooked up:
 * <pre>
 *   viewer.addDropSupport
 *     (DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK,
 *      new Transfer [] { ObjectTransfer.getInstance() },
 *      EditingDomainViewerDropAdapter(viewer));
 * </pre>
 * <p>
 * This implementation prefers to use a {@link ObjectTransfer}, 
 * which short-circuits the transfer process for simple transfers within the workbench,
 * the method {@link #getDragSource} can be overriden to change the behaviour.
 * The implementation also only handles an {@link IStructuredSelection},
 * but the method {@link #extractDragSource} can be overriden to change the behaviour.
 * <p>
 * You can call {@link #setHoverThreshold} to set the amount of time, in milliseconds, 
 * to hover over an item before {@link #hover} is called;
 * the default is 1500 milliseconds.
 */
public class ViewerDropAdapter extends DropTargetAdapter
{
  public static final String copyright = "(c) Copyright IBM Corporation 2000, 2002.";
  /**
   * This is the viewer for which this is a drop target listener.
   */
  protected Viewer viewer;

  /**
   * This is the collection of source objects being dragged.
   */
  protected Collection source;

  /**
   * This is the command created during dragging which provides the feedback and will carry out the action upon completion.
   */
  //  protected Command command;
  protected DragAndDropCommand command;
 
  /**
   * This records the object for which the {@link #command} was created.
   */
  protected Object commandTarget;

  /**
   * The amount of time to hover over a tree item before expanding it
   */
  protected int hoverThreshold = 1500;

  /**
   * The is the time the mouse first started hovering over the current item.
   */
  protected long hoverStart = 0;

  /**
   * This keeps track of the most recent item for the {@link #hoverStart}.
   */
  protected Widget previousItem;

  /**
   * This keeps track of the original operation that was in effect before we set the event.detail in here.
   */
  protected int originalOperation;

  /**
   * This keeps track of the information used to create the current command.
   */
  protected DragAndDropCommandInformation dragAndDropCommandInformation;

  protected DragAndDropManager dragAndDropManager;

  /**
   * This creates and instance of the given domain and viewer.
   */
  public ViewerDropAdapter(Viewer viewer, DragAndDropManager dragAndDropManager)
  {
    this.viewer = viewer;
    this.dragAndDropManager = dragAndDropManager;
  }

  /**
   * This is called when the mouse first enters or starts dragging in the viewer.
   */
  public void dragEnter(DropTargetEvent event)
  {
    originalOperation = event.detail;
    helper(event);
  }

  /**
   * This is called when the mouse leaves or stops dragging in the viewer
   */
  public void dragLeave(DropTargetEvent event)
  {
    // Clean up the command if there is one.
    //
    if (command != null)
    {
//        command.dispose();
      command = null;
      commandTarget = null;
    }

    // Reset the other values.
    //
    previousItem = null;
    hoverStart = 0;
    source = null;
  }

  /**
   * This is called when the operation has changed in some way, typically because the user changes keyboard modifiers.
   */
  public void dragOperationChanged(DropTargetEvent event)
  {
    originalOperation = event.detail;
    helper(event);
  }

  /**
   * This is called repeated when the mouse over the viewer.
   */
  public void dragOver(DropTargetEvent event) 
  {
    helper(event);
  }

  /**
   * This is called just as the mouse is released over the viewer to initiate a drop.
   */
  public void dropAccept(DropTargetEvent event) 
  {
    // There seems to be a bug in SWT that the view may have scrolled.
    // helper(event);
  }

  /**
   * This is called to indate that the drop action should be invoked.
   */
  public void drop(DropTargetEvent event)
  {
    // There seems to be a bug in SWT that the view may have scrolled.
    // helper(event);
    if (dragAndDropCommandInformation != null)
    {
      command = dragAndDropCommandInformation.createCommand();

      // Execute the command
      command.execute();

      // Clean up the state.
      //
      command = null;
      commandTarget = null;
      previousItem = null;
      hoverStart = 0;
      source = null;
    }
  }

  /**
   * This method is called the same way for each of the {@link org.eclipse.swt.dnd.DropTargetListener} methods, except during leave.
   */
  protected void helper(DropTargetEvent event)
  {
    // Try to get the source if there isn't one.
    //
    if (source == null)
    {
      source = getDragSource(event);
    }                   
    else if (event.currentDataType == null)
    {
      setCurrentDataType(event);
    }

    // If there's still no source, wait until the next time to try again.
    //
    if (source == null)
    {
      event.detail = DND.DROP_NONE;
      event.feedback = DND.FEEDBACK_SELECT;
    }
    // Otherwise, if we need to scroll...
    //
    else if (scrollIfNeeded(event))
    {
      // In the case that we scroll, we just do all the work on the next event and only just scroll now.
      //
      event.feedback = DND.FEEDBACK_SELECT;
    }
    else
    {
      // Get the data from the item, if there is one.
      //
      Object target = event.item == null ? null : event.item.getData();
      if (target instanceof TableTreeItem)
      {
        target = ((TableTreeItem)target).getData();
      }

      // Do the logic to determine the hover information.
      // If we're over a new item from before.
      //
      if (event.item != previousItem)
      {
        // Remember the item and the time.
        //
        previousItem = event.item;
        hoverStart = event.time;
      } 
      else if (target != null)
      {
        if (event.time - hoverStart > hoverThreshold)
        {
          hover(target);

          // We don't need to hover over this guy again.
          //
          hoverStart = Integer.MAX_VALUE;
        }
      }

      // Determine if we can create a valid command at the current mouse location.
      //
      boolean valid = false;

      // If we don't have a previous cached command...
      //
      if (command == null)
      {
        // Create the command and test if it is executable.
        //
        commandTarget = target;
        command = dragAndDropManager.createCommand(target, getLocation(event), event.operations, event.detail, source);
        valid = command.canExecute();
      }
      else
      {
        int operation = originalOperation != event.detail ? originalOperation : event.detail;

        // Check if the cached command is able to provide drag and drop feedback.
        //
        if (target == commandTarget)// && command instanceof DragAndDropFeedback)
        {
          float location = getLocation(event);

          dragAndDropCommandInformation = 
            new DragAndDropCommandInformation(target, location, event.operations, operation, source);

          // If so, revalidate the command.
          //
          command.reinitialize(target, location, event.operations, operation, source);
          valid = command.canExecute();
        }
        else
        {
          // If not, dispose the current command and create a new one.
          //
          //          command.dispose();
          commandTarget = target;

          dragAndDropCommandInformation = 
            new DragAndDropCommandInformation(target, getLocation(event), event.operations, operation, source);

          // DragAndDropManager.create(domain, target, getLocation(event), event.operations, operation, source);
          //
          command = dragAndDropCommandInformation.createCommand();

          valid = command.canExecute();
        }
      }

      // If this command can provide detailed drag and drop feedback...
      //
      //if (command instanceof DragAndDropCommand)
      if (command != null)
      {
        // Use the feedback for the operation and mouse point from the command.
        //
        event.detail = command.getOperation();
        event.feedback = command.getFeedback();
      }
      else if (valid)
      {
        // All we can know is to provide selection feedback.
        //
        event.feedback = DND.FEEDBACK_SELECT;
      }
      else
      {
        // There is no executable command, so we'd better nix the whole deal.
        //
        event.detail = DND.DROP_NONE;
        event.feedback = DND.FEEDBACK_SELECT;
      }
    }
  }
    

  protected void setCurrentDataType(DropTargetEvent event)
  {                                
    ObjectTransfer objectTransfer = ObjectTransfer.getInstance();
    TransferData [] dataTypes = event.dataTypes;
    for (int i = 0; i < dataTypes.length; ++i)
    {
      TransferData transferData = dataTypes[i];
      // If the local tansfer supports this datatype, switch to that data type
      //
      if (objectTransfer.isSupportedType(transferData))
      {
        event.currentDataType = transferData;
      }
    }
  }

  /** 
   * This  attempts to extract the drag source from the event early, i.e., before the drop method.
   * This implementation tries to use a {@link org.eclipse.wst.common.ui.dnd.ObjectTransfer}.
   */
  protected Collection getDragSource(DropTargetEvent event)
  {
    // Check whether the current data type can be transfered locally.
    //
    ObjectTransfer objectTransfer = ObjectTransfer.getInstance();
    if (!objectTransfer.isSupportedType(event.currentDataType))
    {
      // Iterate over the data types to see if there is a datatype that supports a local transfer.
      //
      setCurrentDataType(event);
      return null;
    }
    else
    {
      // Transfer the data and extract it.
      //
      Object object = objectTransfer.nativeToJava(event.currentDataType);
      return extractDragSource(object);
    }
  }

  /**
   * This extracts a collection of dragged source objects from the given object retrieved from the transfer agent.
   * This default implementation converts a structured selection into a collection of elements.
   */
  protected Collection extractDragSource(Object object)
  {
    // Transfer the data and convert the structured selection to a collection of objects.
    //
    if (object instanceof IStructuredSelection)
    {
      Collection result = new ArrayList();
      for (Iterator elements = ((IStructuredSelection)object).iterator(); elements.hasNext(); )
      {
        result.add(elements.next());
      }
      return result;
    }
    else
    {
      return Collections.EMPTY_LIST;
    }
  }

  /**
   * This gets the amount of time, in milliseconds, to hover over an item before {@link #hover} is called.
   */
  public int getHoverThreshold()
  {
    return hoverThreshold;
  }

  /**
   * This set the amount of time, in milliseconds, to hover over an item before {@link #hover} is called.
   */
  public void setHoverThreshold(int hoverThreshold)
  {
    this.hoverThreshold = hoverThreshold;
  }

  /**
   * This is called when the cursor has hovered over the given target for longer than {@link #hoverThreshold}.
   */
  protected void hover(Object target)
  {
    if (viewer instanceof AbstractTreeViewer)
    {
      ((AbstractTreeViewer)viewer).expandToLevel(target, 1);
    }
  }

  /** 
   * This returns whether a scroll was performed based on the given drag coordinates.
   */
  protected boolean scrollIfNeeded(DropTargetEvent event)
  {
    // By default we'll not scroll
    //
    boolean result = false;

    // We only handle a tree item right now.
    //
    if (event.item instanceof TreeItem)
    {
      // Tree items have special data that will help.
      //
      TreeItem treeItem = (TreeItem)event.item;

      // We need need the point in the coordinates of the control and the control's bounds.
      //
      Tree tree = treeItem.getParent();
      Point point = tree.toControl(new Point(event.x, event.y));
      Rectangle bounds = tree.getClientArea();

      // This is the distance in pixels from the top or bottom that will cause scrolling.
      //
      int scrollEpsilon = Math.min(treeItem.getBounds().height, bounds.height / 3);

      // This will be the item that should be scrolled into the view.
      //
      TreeItem scrollTreeItem = null;

      // If we should scroll up.
      //
      if (point.y < scrollEpsilon)
      {
        // Determine the parent to find the sibling.
        //
        TreeItem parent = treeItem.getParentItem();
        // Walk through the siblings.
        //
        TreeItem [] children = parent == null ? tree.getItems() : parent.getItems();
        for (int i = 0; i < children.length; ++i)
        {
          // Is this a match.
          //
          if (children[i] == treeItem)
          {
            // If there is a previous sibling...
            //
            if (i > 0)
            {
              scrollTreeItem = children[i - 1];

              // Get the last deepest descendent of this previous sibling.
              //
              for (;;)
              {
                children = scrollTreeItem.getItems();
                if (children != null && children.length != 0 && scrollTreeItem.getExpanded())
                {
                  scrollTreeItem = children[children.length - 1];
                }
                else
                {
                  break;
                }
              }
            }
            else
            {
              // The parent must be the previous.
              //
              scrollTreeItem = parent;
            }

            // We're done after the match.
            //
            break;
          }
        }
      }
      // If we should scroll down...
      //
      else if (bounds.height - point.y < scrollEpsilon)
      {
        // If this thing has visible children, then the first child must be next.
        //
        TreeItem [] children = treeItem.getItems();
        if (children != null && children.length != 0 && treeItem.getExpanded())
        {
          scrollTreeItem = children[0];
        }
        else
        {
          // We need the parent to determine siblings and will walk up the tree if we are the last sibling.
          //
          while (scrollTreeItem == null)
          {
            // If there's no parent, we're done.
            //
            TreeItem parent = treeItem.getParentItem();
            // Walk the children.
            //
            children = parent == null ? tree.getItems() : parent.getItems();
            for (int i = 0; i < children.length; ++i)
            {
              // When we find the child.
              //
              if (children[i] == treeItem)
              {
                // If the next index is a valid index...
                //
                if (++i < children.length)
                {
                  // We've found the item.
                  //
                  scrollTreeItem = children[i];
                }

                // We're done with this parent.
                //
                break;
              }
            }

            if (parent == null)
            {
              break;
            }

            // Walk up.
            //
            treeItem = parent;
          }
        }
      }

      // If we should scroll.
      //
      if (scrollTreeItem != null)
      {
        // Only scroll if we're on an item for a while.
        //
        if (previousItem != null && event.time - hoverStart > 200)
        {
          ScrollBar verticalScrollBar = tree.getVerticalBar();
          if (verticalScrollBar != null)
          {
            int before = verticalScrollBar.getSelection();

            // Make sure the item is scrolled in place.
            //
            tree.showItem(scrollTreeItem);

            // Make sure we don't scroll again quickly.
            //
            previousItem = null;

            // Indicate that we've done a scroll and nothing else should be done.
            //
            result = before != verticalScrollBar.getSelection();
          }
        }
        else
        {
          // If the item changes, reset the timer information.
          //
          if (event.item != previousItem)
          {
            previousItem = event.item;
            hoverStart = event.time;
          }
        }
      }
    }
    else if (event.item instanceof TableItem)
    {
      // Table items have special data that will help.
      //
      TableItem tableItem = (TableItem)event.item;

      // We need need the point in the coordinates of the control and the control's bounds.
      //
      Table table = tableItem.getParent();
      Point point = table.toControl(new Point(event.x, event.y));
      Rectangle bounds = table.getClientArea();
      if (table.getHeaderVisible())
      {
        int offset = table.getItemHeight();
        bounds.y += offset;
        bounds.height -= offset;
        point.y -= offset;
      }

      // The position of this item.
      //
      int index = table.indexOf(tableItem);

      // This is the distance in pixels from the top or bottom that will cause scrolling.
      //
      int scrollEpsilon = Math.min(tableItem.getBounds(0).height, bounds.height / 3);

      // This will be the item that should be scrolled into the view.
      //
      TableItem scrollTableItem = null;

      // If we should scroll up.
      //
      if (point.y < scrollEpsilon)
      {
        if (index > 0)
        {
          scrollTableItem = table.getItems()[index - 1];
        }
      }
      // If we should scroll down...
      //
      else if (bounds.height - point.y < scrollEpsilon)
      {
        if (index + 1 < table.getItems().length)
        {
          scrollTableItem =  table.getItems()[index + 1];
        }
      }

      // If we should scroll.
      //
      if (scrollTableItem != null)
      {
        // Only scroll if we're on an item for a while.
        //
        if (previousItem != null && event.time - hoverStart > 200)
        {
          ScrollBar verticalScrollBar = table.getVerticalBar();
          if (verticalScrollBar != null)
          {
            int before = verticalScrollBar.getSelection();

            // Make sure the item is scrolled in place.
            //
            table.showItem(scrollTableItem);

            // Make sure we don't scroll again quickly.
            //
            previousItem = null;

            // Indicate that we've done a scroll and nothing else should be done.
            //
            result = before != verticalScrollBar.getSelection();
          }
        }
        else
        {
          // If the item changes, reset the timer information.
          //
          if (event.item != previousItem)
          {
            previousItem = event.item;
            hoverStart = event.time;
          }
        }
      }
    }

    return result;
  }

  protected static float getLocation(DropTargetEvent event) 
  {
    if (event.item instanceof TreeItem)
    {
      TreeItem treeItem = (TreeItem)event.item;
      Control control = treeItem.getParent();
      Point point = control.toControl(new Point(event.x, event.y));
      Rectangle bounds = treeItem.getBounds();
      return (float)(point.y - bounds.y) / (float)bounds.height;
    }
    else if (event.item instanceof TableItem)
    {
      TableItem tableItem = (TableItem)event.item;
      Control control = tableItem.getParent();
      Point point = control.toControl(new Point(event.x, event.y));
      Rectangle bounds = tableItem.getBounds(0);
      return (float)(point.y - bounds.y) / (float)bounds.height;
    }
    else
    {
      return 0.0F;
    }
  }

  protected class DragAndDropCommandInformation
  {
    //    protected EditingDomain domain;
    protected Object target;
    protected float location;
    protected int operations;
    protected int operation;
    protected Collection source;
    public DragAndDropCommandInformation
      (Object target, float location, int operations, int operation, Collection source)
    {
      this.target = target;
      this.location = location;
      this.operations = operations;
      this.operation = operation;
      this.source = new ArrayList(source);
    }

    public DragAndDropCommand createCommand()
    {
      return dragAndDropManager.createCommand(target, location, operations, operation, source);
    }
  }
}
