/*
 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.awt.dnd;

import java.awt.AWTError;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.TooManyListenersException;

import sun.awt.AWTAccessor;
import sun.awt.ComponentFactory;

/**
 * The {@code DragSourceContext} class is responsible for managing the
 * initiator side of the Drag and Drop protocol. In particular, it is responsible
 * for managing drag event notifications to the
 * {@linkplain DragSourceListener DragSourceListeners}
 * and {@linkplain DragSourceMotionListener DragSourceMotionListeners}, and providing the
 * {@link Transferable} representing the source data for the drag operation.
 * <p>
 * Note that the {@code DragSourceContext} itself
 * implements the {@code DragSourceListener} and
 * {@code DragSourceMotionListener} interfaces.
 * This is to allow the platform peer
 * (the {@link DragSourceContextPeer} instance)
 * created by the {@link DragSource} to notify
 * the {@code DragSourceContext} of
 * state changes in the ongoing operation. This allows the
 * {@code DragSourceContext} object to interpose
 * itself between the platform and the
 * listeners provided by the initiator of the drag operation.
 * <p>
 * <a id="defaultCursor"></a>
 * By default, {@code DragSourceContext} sets the cursor as appropriate
 * for the current state of the drag and drop operation. For example, if
 * the user has chosen {@linkplain DnDConstants#ACTION_MOVE the move action},
 * and the pointer is over a target that accepts
 * the move action, the default move cursor is shown. When
 * the pointer is over an area that does not accept the transfer,
 * the default "no drop" cursor is shown.
 * <p>
 * This default handling mechanism is disabled when a custom cursor is set
 * by the {@link #setCursor} method. When the default handling is disabled,
 * it becomes the responsibility
 * of the developer to keep the cursor up to date, by listening
 * to the {@code DragSource} events and calling the {@code setCursor()} method.
 * Alternatively, you can provide custom cursor behavior by providing
 * custom implementations of the {@code DragSource}
 * and the {@code DragSourceContext} classes.
 *
 * @see DragSourceListener
 * @see DragSourceMotionListener
 * @see DnDConstants
 * @since 1.2
 */

public class DragSourceContext
    implements DragSourceListener, DragSourceMotionListener, Serializable {

    private static final long serialVersionUID = -115407898692194719L;

    // used by updateCurrentCursor

    /**
     * An {@code int} used by updateCurrentCursor()
     * indicating that the {@code Cursor} should change
     * to the default (no drop) {@code Cursor}.
     */
    protected static final int DEFAULT = 0;

    /**
     * An {@code int} used by updateCurrentCursor()
     * indicating that the {@code Cursor}
     * has entered a {@code DropTarget}.
     */
    protected static final int ENTER   = 1;

    /**
     * An {@code int} used by updateCurrentCursor()
     * indicating that the {@code Cursor} is
     * over a {@code DropTarget}.
     */
    protected static final int OVER    = 2;

    /**
     * An {@code int} used by updateCurrentCursor()
     * indicating that the user operation has changed.
     */

    protected static final int CHANGED = 3;

    static {
        AWTAccessor.setDragSourceContextAccessor(dsc -> dsc.peer);
    }

    /**
     * Called from {@code DragSource}, this constructor creates a new
     * {@code DragSourceContext} given the
     * {@code DragSourceContextPeer} for this Drag, the
     * {@code DragGestureEvent} that triggered the Drag, the initial
     * {@code Cursor} to use for the Drag, an (optional)
     * {@code Image} to display while the Drag is taking place, the offset
     * of the {@code Image} origin from the hotspot at the instant of the
     * triggering event, the {@code Transferable} subject data, and the
     * {@code DragSourceListener} to use during the Drag and Drop
     * operation.
     * <br>
     * If {@code DragSourceContextPeer} is {@code null}
     * {@code NullPointerException} is thrown.
     * <br>
     * If {@code DragGestureEvent} is {@code null}
     * {@code NullPointerException} is thrown.
     * <br>
     * If {@code Cursor} is {@code null} no exception is thrown and
     * the default drag cursor behavior is activated for this drag operation.
     * <br>
     * If {@code Image} is {@code null} no exception is thrown.
     * <br>
     * If {@code Image} is not {@code null} and the offset is
     * {@code null NullPointerException} is thrown.
     * <br>
     * If {@code Transferable} is {@code null}
     * {@code NullPointerException} is thrown.
     * <br>
     * If {@code DragSourceListener} is {@code null} no exception
     * is thrown.
     *
     * @param trigger    the triggering event
     * @param dragCursor     the initial {@code Cursor} for this drag operation
     *                       or {@code null} for the default cursor handling;
     *                       see <a href="DragSourceContext.html#defaultCursor">class level documentation</a>
     *                       for more details on the cursor handling mechanism during drag and drop
     * @param dragImage  the {@code Image} to drag (or {@code null})
     * @param offset     the offset of the image origin from the hotspot at the
     *                   instant of the triggering event
     * @param t          the {@code Transferable}
     * @param dsl        the {@code DragSourceListener}
     *
     * @throws IllegalArgumentException if the {@code Component} associated
     *         with the trigger event is {@code null}.
     * @throws IllegalArgumentException if the {@code DragSource} for the
     *         trigger event is {@code null}.
     * @throws IllegalArgumentException if the drag action for the
     *         trigger event is {@code DnDConstants.ACTION_NONE}.
     * @throws IllegalArgumentException if the source actions for the
     *         {@code DragGestureRecognizer} associated with the trigger
     *         event are equal to {@code DnDConstants.ACTION_NONE}.
     * @throws NullPointerException if dscp, trigger, or t are null, or
     *         if dragImage is non-null and offset is null
     */
    public DragSourceContext(DragGestureEvent trigger, Cursor dragCursor,
                             Image dragImage, Point offset, Transferable t,
                             DragSourceListener dsl) {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        if (!(toolkit instanceof ComponentFactory)) {
            throw new AWTError("Unsupported toolkit: " + toolkit);
        }
        DragSourceContextPeer dscp = ((ComponentFactory) toolkit).
                createDragSourceContextPeer(trigger);

        if (dscp == null) {
            throw new NullPointerException("DragSourceContextPeer");
        }

        if (trigger == null) {
            throw new NullPointerException("Trigger");
        }

        if (trigger.getDragSource() == null) {
            throw new IllegalArgumentException("DragSource");
        }

        if (trigger.getComponent() == null) {
            throw new IllegalArgumentException("Component");
        }

        if (trigger.getSourceAsDragGestureRecognizer().getSourceActions() ==
                 DnDConstants.ACTION_NONE) {
            throw new IllegalArgumentException("source actions");
        }

        if (trigger.getDragAction() == DnDConstants.ACTION_NONE) {
            throw new IllegalArgumentException("no drag action");
        }

        if (t == null) {
            throw new NullPointerException("Transferable");
        }

        if (dragImage != null && offset == null) {
            throw new NullPointerException("offset");
        }

        peer         = dscp;
        this.trigger = trigger;
        cursor       = dragCursor;
        transferable = t;
        listener     = dsl;
        sourceActions =
            trigger.getSourceAsDragGestureRecognizer().getSourceActions();

        useCustomCursor = (dragCursor != null);

        updateCurrentCursor(trigger.getDragAction(), getSourceActions(), DEFAULT);
    }

    /**
     * Returns the {@code DragSource}
     * that instantiated this {@code DragSourceContext}.
     *
     * @return the {@code DragSource} that
     *   instantiated this {@code DragSourceContext}
     */

    public DragSource   getDragSource() { return trigger.getDragSource(); }

    /**
     * Returns the {@code Component} associated with this
     * {@code DragSourceContext}.
     *
     * @return the {@code Component} that started the drag
     */

    public Component    getComponent() { return trigger.getComponent(); }

    /**
     * Returns the {@code DragGestureEvent}
     * that initially triggered the drag.
     *
     * @return the Event that triggered the drag
     */

    public DragGestureEvent getTrigger() { return trigger; }

    /**
     * Returns a bitwise mask of {@code DnDConstants} that
     * represent the set of drop actions supported by the drag source for the
     * drag operation associated with this {@code DragSourceContext}.
     *
     * @return the drop actions supported by the drag source
     */
    public int  getSourceActions() {
        return sourceActions;
    }

    /**
     * Sets the custom cursor for this drag operation to the specified
     * {@code Cursor}.  If the specified {@code Cursor}
     * is {@code null}, the default drag cursor behavior is
     * activated for this drag operation, otherwise it is deactivated.
     *
     * @param c     the initial {@code Cursor} for this drag operation,
     *                       or {@code null} for the default cursor handling;
     *                       see {@linkplain Cursor class
     *                       level documentation} for more details
     *                       on the cursor handling during drag and drop
     *
     */

    public synchronized void setCursor(Cursor c) {
        useCustomCursor = (c != null);
        setCursorImpl(c);
    }

    /**
     * Returns the current custom drag {@code Cursor}.
     *
     * @return the current custom drag {@code Cursor}, if it was set
     *         otherwise returns {@code null}.
     * @see #setCursor
     */

    public Cursor getCursor() { return cursor; }

    /**
     * Add a {@code DragSourceListener} to this
     * {@code DragSourceContext} if one has not already been added.
     * If a {@code DragSourceListener} already exists,
     * this method throws a {@code TooManyListenersException}.
     *
     * @param dsl the {@code DragSourceListener} to add.
     * Note that while {@code null} is not prohibited,
     * it is not acceptable as a parameter.
     *
     * @throws TooManyListenersException if
     * a {@code DragSourceListener} has already been added
     */

    public synchronized void addDragSourceListener(DragSourceListener dsl) throws TooManyListenersException {
        if (dsl == null) return;

        if (equals(dsl)) throw new IllegalArgumentException("DragSourceContext may not be its own listener");

        if (listener != null)
            throw new TooManyListenersException();
        else
            listener = dsl;
    }

    /**
     * Removes the specified {@code DragSourceListener}
     * from  this {@code DragSourceContext}.
     *
     * @param dsl the {@code DragSourceListener} to remove;
     *     note that while {@code null} is not prohibited,
     *     it is not acceptable as a parameter
     */

    public synchronized void removeDragSourceListener(DragSourceListener dsl) {
        if (listener != null && listener.equals(dsl)) {
            listener = null;
        } else
            throw new IllegalArgumentException();
    }

    /**
     * Notifies the peer that the {@code Transferable}'s
     * {@code DataFlavor}s have changed.
     */

    public void transferablesFlavorsChanged() {
        if (peer != null) peer.transferablesFlavorsChanged();
    }

    /**
     * Calls {@code dragEnter} on the
     * {@code DragSourceListener}s registered with this
     * {@code DragSourceContext} and with the associated
     * {@code DragSource}, and passes them the specified
     * {@code DragSourceDragEvent}.
     *
     * @param dsde the {@code DragSourceDragEvent}
     */
    public void dragEnter(DragSourceDragEvent dsde) {
        DragSourceListener dsl = listener;
        if (dsl != null) {
            dsl.dragEnter(dsde);
        }
        getDragSource().processDragEnter(dsde);

        updateCurrentCursor(getSourceActions(), dsde.getTargetActions(), ENTER);
    }

    /**
     * Calls {@code dragOver} on the
     * {@code DragSourceListener}s registered with this
     * {@code DragSourceContext} and with the associated
     * {@code DragSource}, and passes them the specified
     * {@code DragSourceDragEvent}.
     *
     * @param dsde the {@code DragSourceDragEvent}
     */
    public void dragOver(DragSourceDragEvent dsde) {
        DragSourceListener dsl = listener;
        if (dsl != null) {
            dsl.dragOver(dsde);
        }
        getDragSource().processDragOver(dsde);

        updateCurrentCursor(getSourceActions(), dsde.getTargetActions(), OVER);
    }

    /**
     * Calls {@code dragExit} on the
     * {@code DragSourceListener}s registered with this
     * {@code DragSourceContext} and with the associated
     * {@code DragSource}, and passes them the specified
     * {@code DragSourceEvent}.
     *
     * @param dse the {@code DragSourceEvent}
     */
    public void dragExit(DragSourceEvent dse) {
        DragSourceListener dsl = listener;
        if (dsl != null) {
            dsl.dragExit(dse);
        }
        getDragSource().processDragExit(dse);

        updateCurrentCursor(DnDConstants.ACTION_NONE, DnDConstants.ACTION_NONE, DEFAULT);
    }

    /**
     * Calls {@code dropActionChanged} on the
     * {@code DragSourceListener}s registered with this
     * {@code DragSourceContext} and with the associated
     * {@code DragSource}, and passes them the specified
     * {@code DragSourceDragEvent}.
     *
     * @param dsde the {@code DragSourceDragEvent}
     */
    public void dropActionChanged(DragSourceDragEvent dsde) {
        DragSourceListener dsl = listener;
        if (dsl != null) {
            dsl.dropActionChanged(dsde);
        }
        getDragSource().processDropActionChanged(dsde);

        updateCurrentCursor(getSourceActions(), dsde.getTargetActions(), CHANGED);
    }

    /**
     * Calls {@code dragDropEnd} on the
     * {@code DragSourceListener}s registered with this
     * {@code DragSourceContext} and with the associated
     * {@code DragSource}, and passes them the specified
     * {@code DragSourceDropEvent}.
     *
     * @param dsde the {@code DragSourceDropEvent}
     */
    public void dragDropEnd(DragSourceDropEvent dsde) {
        DragSourceListener dsl = listener;
        if (dsl != null) {
            dsl.dragDropEnd(dsde);
        }
        getDragSource().processDragDropEnd(dsde);
    }

    /**
     * Calls {@code dragMouseMoved} on the
     * {@code DragSourceMotionListener}s registered with the
     * {@code DragSource} associated with this
     * {@code DragSourceContext}, and them passes the specified
     * {@code DragSourceDragEvent}.
     *
     * @param dsde the {@code DragSourceDragEvent}
     * @since 1.4
     */
    public void dragMouseMoved(DragSourceDragEvent dsde) {
        getDragSource().processDragMouseMoved(dsde);
    }

    /**
     * Returns the {@code Transferable} associated with
     * this {@code DragSourceContext}.
     *
     * @return the {@code Transferable}
     */
    public Transferable getTransferable() { return transferable; }

    /**
     * If the default drag cursor behavior is active, this method
     * sets the default drag cursor for the specified actions
     * supported by the drag source, the drop target action,
     * and status, otherwise this method does nothing.
     *
     * @param sourceAct the actions supported by the drag source
     * @param targetAct the drop target action
     * @param status one of the fields {@code DEFAULT},
     *               {@code ENTER}, {@code OVER},
     *               {@code CHANGED}
     */
    @SuppressWarnings("fallthrough")
    protected synchronized void updateCurrentCursor(int sourceAct, int targetAct, int status) {

        // if the cursor has been previously set then don't do any defaults
        // processing.

        if (useCustomCursor) {
            return;
        }

        // do defaults processing

        Cursor c = null;

        switch (status) {
            default:
                targetAct = DnDConstants.ACTION_NONE;
            case ENTER:
            case OVER:
            case CHANGED:
                int    ra = sourceAct & targetAct;

                if (ra == DnDConstants.ACTION_NONE) { // no drop possible
                    if ((sourceAct & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK)
                        c = DragSource.DefaultLinkNoDrop;
                    else if ((sourceAct & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE)
                        c = DragSource.DefaultMoveNoDrop;
                    else
                        c = DragSource.DefaultCopyNoDrop;
                } else { // drop possible
                    if ((ra & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK)
                        c = DragSource.DefaultLinkDrop;
                    else if ((ra & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE)
                        c = DragSource.DefaultMoveDrop;
                    else
                        c = DragSource.DefaultCopyDrop;
                }
        }

        setCursorImpl(c);
    }

    private void setCursorImpl(Cursor c) {
        if (cursor == null || !cursor.equals(c)) {
            cursor = c;
            if (peer != null) peer.setCursor(cursor);
        }
    }

    /**
     * Serializes this {@code DragSourceContext}. This method first
     * performs default serialization. Next, this object's
     * {@code Transferable} is written out if and only if it can be
     * serialized. If not, {@code null} is written instead. In this case,
     * a {@code DragSourceContext} created from the resulting deserialized
     * stream will contain a dummy {@code Transferable} which supports no
     * {@code DataFlavor}s. Finally, this object's
     * {@code DragSourceListener} is written out if and only if it can be
     * serialized. If not, {@code null} is written instead.
     *
     * @serialData The default serializable fields, in alphabetical order,
     *             followed by either a {@code Transferable} instance, or
     *             {@code null}, followed by either a
     *             {@code DragSourceListener} instance, or
     *             {@code null}.
     * @since 1.4
     */
    private void writeObject(ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();

        s.writeObject(SerializationTester.test(transferable)
                      ? transferable : null);
        s.writeObject(SerializationTester.test(listener)
                      ? listener : null);
    }

    /**
     * Deserializes this {@code DragSourceContext}. This method first
     * performs default deserialization for all non-{@code transient}
     * fields. This object's {@code Transferable} and
     * {@code DragSourceListener} are then deserialized as well by using
     * the next two objects in the stream. If the resulting
     * {@code Transferable} is {@code null}, this object's
     * {@code Transferable} is set to a dummy {@code Transferable}
     * which supports no {@code DataFlavor}s.
     *
     * @since 1.4
     */
    private void readObject(ObjectInputStream s)
        throws ClassNotFoundException, IOException
    {
        ObjectInputStream.GetField f = s.readFields();

        DragGestureEvent newTrigger = (DragGestureEvent)f.get("trigger", null);
        if (newTrigger == null) {
            throw new InvalidObjectException("Null trigger");
        }
        if (newTrigger.getDragSource() == null) {
            throw new InvalidObjectException("Null DragSource");
        }
        if (newTrigger.getComponent() == null) {
            throw new InvalidObjectException("Null trigger component");
        }

        int newSourceActions = f.get("sourceActions", 0)
                & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
        if (newSourceActions == DnDConstants.ACTION_NONE) {
            throw new InvalidObjectException("Invalid source actions");
        }
        int triggerActions = newTrigger.getDragAction();
        if (triggerActions != DnDConstants.ACTION_COPY &&
                triggerActions != DnDConstants.ACTION_MOVE &&
                triggerActions != DnDConstants.ACTION_LINK) {
            throw new InvalidObjectException("No drag action");
        }
        trigger = newTrigger;

        cursor = (Cursor)f.get("cursor", null);
        useCustomCursor = f.get("useCustomCursor", false);
        sourceActions = newSourceActions;

        transferable = (Transferable)s.readObject();
        listener = (DragSourceListener)s.readObject();

        // Implementation assumes 'transferable' is never null.
        if (transferable == null) {
            if (emptyTransferable == null) {
                emptyTransferable = new Transferable() {
                        public DataFlavor[] getTransferDataFlavors() {
                            return new DataFlavor[0];
                        }
                        public boolean isDataFlavorSupported(DataFlavor flavor)
                        {
                            return false;
                        }
                        public Object getTransferData(DataFlavor flavor)
                            throws UnsupportedFlavorException
                        {
                            throw new UnsupportedFlavorException(flavor);
                        }
                    };
            }
            transferable = emptyTransferable;
        }
    }

    private static Transferable emptyTransferable;

    /*
     * fields
     */
    private final transient DragSourceContextPeer peer;

    /**
     * The event which triggered the start of the drag.
     *
     * @serial
     */
    private DragGestureEvent    trigger;

    /**
     * The current drag cursor.
     *
     * @serial
     */
    private Cursor              cursor;

    private transient Transferable      transferable;

    private transient DragSourceListener    listener;

    /**
     * {@code true} if the custom drag cursor is used instead of the
     * default one.
     *
     * @serial
     */
    private boolean useCustomCursor;

    /**
     * A bitwise mask of {@code DnDConstants} that represents the set of
     * drop actions supported by the drag source for the drag operation associated
     * with this {@code DragSourceContext.}
     *
     * @serial
     */
    private int sourceActions;
}
