/*
 * Copyright (c) 2000, 2007, 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 sun.awt.dnd;

import java.awt.Component;
import java.awt.Point;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.awt.dnd.DnDConstants;

import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetListener;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.InvalidDnDOperationException;

import java.awt.dnd.peer.DropTargetContextPeer;

import java.util.HashSet;
import java.util.Map;
import java.util.Arrays;

import sun.util.logging.PlatformLogger;

import java.io.IOException;
import java.io.InputStream;

import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
import sun.security.util.SecurityConstants;

/**
 * <p>
 * The SunDropTargetContextPeer class is the generic class responsible for handling
 * the interaction between a windowing systems DnD system and Java.
 * </p>
 *
 * @since JDK1.3.1
 *
 */

public abstract class SunDropTargetContextPeer implements DropTargetContextPeer, Transferable {

    /*
     * A boolean constant that requires the peer to wait until the
     * SunDropTargetEvent is processed and return the status back
     * to the native code.
     */
    public static final boolean DISPATCH_SYNC = true;
    private   DropTarget              currentDT;
    private   DropTargetContext       currentDTC;
    private   long[]                  currentT;
    private   int                     currentA;   // target actions
    private   int                     currentSA;  // source actions
    private   int                     currentDA;  // current drop action
    private   int                     previousDA;

    private   long                    nativeDragContext;

    private   Transferable            local;

    private boolean                   dragRejected = false;

    protected int                     dropStatus   = STATUS_NONE;
    protected boolean                 dropComplete = false;

    /*
     * global lock
     */

    protected static final Object _globalLock = new Object();

    private static final PlatformLogger dndLog = PlatformLogger.getLogger("sun.awt.dnd.SunDropTargetContextPeer");

    /*
     * a primitive mechanism for advertising intra-JVM Transferables
     */

    protected static Transferable         currentJVMLocalSourceTransferable = null;

    public static void setCurrentJVMLocalSourceTransferable(Transferable t) throws InvalidDnDOperationException {
        synchronized(_globalLock) {
            if (t != null && currentJVMLocalSourceTransferable != null) {
                    throw new InvalidDnDOperationException();
            } else {
                currentJVMLocalSourceTransferable = t;
            }
        }
    }

    /**
     * obtain the transferable iff the operation is in the same VM
     */

    private static Transferable getJVMLocalSourceTransferable() {
        return currentJVMLocalSourceTransferable;
    }

    /*
     * constants used by dropAccept() or dropReject()
     */

    protected final static int STATUS_NONE   =  0; // none pending
    protected final static int STATUS_WAIT   =  1; // drop pending
    protected final static int STATUS_ACCEPT =  2;
    protected final static int STATUS_REJECT = -1;

    /**
     * create the peer
     */

    public SunDropTargetContextPeer() {
        super();
    }

    /**
     * @return the DropTarget associated with this peer
     */

    public DropTarget getDropTarget() { return currentDT; }

    /**
     * @param actions set the current actions
     */

    public synchronized void setTargetActions(int actions) {
        currentA = actions &
            (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK);
    }

    /**
     * @return the current target actions
     */

    public int getTargetActions() {
        return currentA;
    }

    /**
     * get the Transferable associated with the drop
     */

    public Transferable getTransferable() {
        return this;
    }

    /**
     * @return current DataFlavors available
     */
    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!

    public DataFlavor[] getTransferDataFlavors() {
        final Transferable    localTransferable = local;

        if (localTransferable != null) {
            return localTransferable.getTransferDataFlavors();
        } else {
            return DataTransferer.getInstance().getFlavorsForFormatsAsArray
                (currentT, DataTransferer.adaptFlavorMap
                    (currentDT.getFlavorMap()));
        }
    }

    /**
     * @return if the flavor is supported
     */

    public boolean isDataFlavorSupported(DataFlavor df) {
        Transferable localTransferable = local;

        if (localTransferable != null) {
            return localTransferable.isDataFlavorSupported(df);
        } else {
            return DataTransferer.getInstance().getFlavorsForFormats
                (currentT, DataTransferer.adaptFlavorMap
                    (currentDT.getFlavorMap())).
                containsKey(df);
        }
    }

    /**
     * @return the data
     */

    public Object getTransferData(DataFlavor df)
      throws UnsupportedFlavorException, IOException,
        InvalidDnDOperationException
    {

        SecurityManager sm = System.getSecurityManager();
        try {
            if (!dropComplete && sm != null) {
                sm.checkSystemClipboardAccess();
            }
        } catch (Exception e) {
            Thread currentThread = Thread.currentThread();
            currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, e);
            return null;
        }

        Long lFormat = null;
        Transferable localTransferable = local;

        if (localTransferable != null) {
            return localTransferable.getTransferData(df);
        }

        if (dropStatus != STATUS_ACCEPT || dropComplete) {
            throw new InvalidDnDOperationException("No drop current");
        }

        Map flavorMap = DataTransferer.getInstance().getFlavorsForFormats
            (currentT, DataTransferer.adaptFlavorMap
                (currentDT.getFlavorMap()));

        lFormat = (Long)flavorMap.get(df);
        if (lFormat == null) {
            throw new UnsupportedFlavorException(df);
        }

        if (df.isRepresentationClassRemote() &&
            currentDA != DnDConstants.ACTION_LINK) {
            throw new InvalidDnDOperationException("only ACTION_LINK is permissable for transfer of java.rmi.Remote objects");
        }

        final long format = lFormat.longValue();
        Object ret = getNativeData(format);

        if (ret instanceof byte[]) {
            try {
                return DataTransferer.getInstance().
                    translateBytes((byte[])ret, df, format, this);
            } catch (IOException e) {
                throw new InvalidDnDOperationException(e.getMessage());
            }
        } else if (ret instanceof InputStream) {
            try {
                return DataTransferer.getInstance().
                    translateStream((InputStream)ret, df, format, this);
            } catch (IOException e) {
                throw new InvalidDnDOperationException(e.getMessage());
            }
        } else {
            throw new IOException("no native data was transfered");
        }
    }

    protected abstract Object getNativeData(long format)
      throws IOException;

    /**
     * @return if the transfer is a local one
     */
    public boolean isTransferableJVMLocal() {
        return local != null || getJVMLocalSourceTransferable() != null;
    }

    private int handleEnterMessage(final Component component,
                                   final int x, final int y,
                                   final int dropAction,
                                   final int actions, final long[] formats,
                                   final long nativeCtxt) {
        return postDropTargetEvent(component, x, y, dropAction, actions,
                                   formats, nativeCtxt,
                                   SunDropTargetEvent.MOUSE_ENTERED,
                                   SunDropTargetContextPeer.DISPATCH_SYNC);
    }

    /**
     * actual processing on EventQueue Thread
     */

    protected void processEnterMessage(SunDropTargetEvent event) {
        Component  c    = (Component)event.getSource();
        DropTarget dt   = c.getDropTarget();
        Point      hots = event.getPoint();

        local = getJVMLocalSourceTransferable();

        if (currentDTC != null) { // some wreckage from last time
            currentDTC.removeNotify();
            currentDTC = null;
        }

        if (c.isShowing() && dt != null && dt.isActive()) {
            currentDT  = dt;
            currentDTC = currentDT.getDropTargetContext();

            currentDTC.addNotify(this);

            currentA   = dt.getDefaultActions();

            try {
                ((DropTargetListener)dt).dragEnter(new DropTargetDragEvent(currentDTC,
                                                                           hots,
                                                                           currentDA,
                                                                           currentSA));
            } catch (Exception e) {
                e.printStackTrace();
                currentDA = DnDConstants.ACTION_NONE;
            }
        } else {
            currentDT  = null;
            currentDTC = null;
            currentDA   = DnDConstants.ACTION_NONE;
            currentSA   = DnDConstants.ACTION_NONE;
            currentA   = DnDConstants.ACTION_NONE;
        }

    }

    /**
     * upcall to handle exit messages
     */

    private void handleExitMessage(final Component component,
                                   final long nativeCtxt) {
        /*
         * Even though the return value is irrelevant for this event, it is
         * dispatched synchronously to fix 4393148 properly.
         */
        postDropTargetEvent(component, 0, 0, DnDConstants.ACTION_NONE,
                            DnDConstants.ACTION_NONE, null, nativeCtxt,
                            SunDropTargetEvent.MOUSE_EXITED,
                            SunDropTargetContextPeer.DISPATCH_SYNC);
    }

    /**
     *
     */

    protected void processExitMessage(SunDropTargetEvent event) {
        Component         c   = (Component)event.getSource();
        DropTarget        dt  = c.getDropTarget();
        DropTargetContext dtc = null;

        if (dt == null) {
            currentDT = null;
            currentT  = null;

            if (currentDTC != null) {
                currentDTC.removeNotify();
            }

            currentDTC = null;

            return;
        }

        if (dt != currentDT) {

            if (currentDTC != null) {
                currentDTC.removeNotify();
            }

            currentDT  = dt;
            currentDTC = dt.getDropTargetContext();

            currentDTC.addNotify(this);
        }

        dtc = currentDTC;

        if (dt.isActive()) try {
            ((DropTargetListener)dt).dragExit(new DropTargetEvent(dtc));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            currentA  = DnDConstants.ACTION_NONE;
            currentSA = DnDConstants.ACTION_NONE;
            currentDA = DnDConstants.ACTION_NONE;
            currentDT = null;
            currentT  = null;

            currentDTC.removeNotify();
            currentDTC = null;

            local = null;

            dragRejected = false;
        }
    }

    private int handleMotionMessage(final Component component,
                                    final int x, final int y,
                                    final int dropAction,
                                    final int actions, final long[] formats,
                                    final long nativeCtxt) {
        return postDropTargetEvent(component, x, y, dropAction, actions,
                                   formats, nativeCtxt,
                                   SunDropTargetEvent.MOUSE_DRAGGED,
                                   SunDropTargetContextPeer.DISPATCH_SYNC);
    }

    /**
     *
     */

    protected void processMotionMessage(SunDropTargetEvent event,
                                      boolean operationChanged) {
        Component         c    = (Component)event.getSource();
        Point             hots = event.getPoint();
        int               id   = event.getID();
        DropTarget        dt   = c.getDropTarget();
        DropTargetContext dtc  = null;

        if (c.isShowing() && (dt != null) && dt.isActive()) {
            if (currentDT != dt) {
                if (currentDTC != null) {
                    currentDTC.removeNotify();
                }

                currentDT  = dt;
                currentDTC = null;
            }

            dtc = currentDT.getDropTargetContext();
            if (dtc != currentDTC) {
                if (currentDTC != null) {
                    currentDTC.removeNotify();
                }

                currentDTC = dtc;
                currentDTC.addNotify(this);
            }

            currentA = currentDT.getDefaultActions();

            try {
                DropTargetDragEvent dtde = new DropTargetDragEvent(dtc,
                                                                   hots,
                                                                   currentDA,
                                                                   currentSA);
                DropTargetListener dtl = (DropTargetListener)dt;
                if (operationChanged) {
                    dtl.dropActionChanged(dtde);
                } else {
                    dtl.dragOver(dtde);
                }

                if (dragRejected) {
                    currentDA = DnDConstants.ACTION_NONE;
                }
            } catch (Exception e) {
                e.printStackTrace();
                currentDA = DnDConstants.ACTION_NONE;
            }
        } else {
            currentDA = DnDConstants.ACTION_NONE;
        }
    }

    /**
     * upcall to handle the Drop message
     */

    private void handleDropMessage(final Component component,
                                   final int x, final int y,
                                   final int dropAction, final int actions,
                                   final long[] formats,
                                   final long nativeCtxt) {
        postDropTargetEvent(component, x, y, dropAction, actions,
                            formats, nativeCtxt,
                            SunDropTargetEvent.MOUSE_DROPPED,
                            !SunDropTargetContextPeer.DISPATCH_SYNC);
    }

    /**
     *
     */

    protected void processDropMessage(SunDropTargetEvent event) {
        Component  c    = (Component)event.getSource();
        Point      hots = event.getPoint();
        DropTarget dt   = c.getDropTarget();

        dropStatus   = STATUS_WAIT; // drop pending ACK
        dropComplete = false;

        if (c.isShowing() && dt != null && dt.isActive()) {
            DropTargetContext dtc = dt.getDropTargetContext();

            currentDT = dt;

            if (currentDTC != null) {
                currentDTC.removeNotify();
            }

            currentDTC = dtc;
            currentDTC.addNotify(this);
            currentA = dt.getDefaultActions();

            synchronized(_globalLock) {
                if ((local = getJVMLocalSourceTransferable()) != null)
                    setCurrentJVMLocalSourceTransferable(null);
            }

            try {
                ((DropTargetListener)dt).drop(new DropTargetDropEvent(dtc,
                                                                      hots,
                                                                      currentDA,
                                                                      currentSA,
                                                                      local != null));
            } finally {
                if (dropStatus == STATUS_WAIT) {
                    rejectDrop();
                } else if (dropComplete == false) {
                    dropComplete(false);
                }
            }
        } else {
            rejectDrop();
        }
    }

    protected int postDropTargetEvent(final Component component,
                                      final int x, final int y,
                                      final int dropAction,
                                      final int actions,
                                      final long[] formats,
                                      final long nativeCtxt,
                                      final int eventID,
                                      final boolean dispatchType) {
        AppContext appContext = SunToolkit.targetToAppContext(component);

        EventDispatcher dispatcher =
            new EventDispatcher(this, dropAction, actions, formats, nativeCtxt,
                                dispatchType);

        SunDropTargetEvent event =
            new SunDropTargetEvent(component, eventID, x, y, dispatcher);

        if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) {
            DataTransferer.getInstance().getToolkitThreadBlockedHandler().lock();
        }

        // schedule callback
        SunToolkit.postEvent(appContext, event);

        eventPosted(event);

        if (dispatchType == SunDropTargetContextPeer.DISPATCH_SYNC) {
            while (!dispatcher.isDone()) {
                DataTransferer.getInstance().getToolkitThreadBlockedHandler().enter();
            }

            DataTransferer.getInstance().getToolkitThreadBlockedHandler().unlock();

            // return target's response
            return dispatcher.getReturnValue();
        } else {
            return 0;
        }
    }

    /**
     * acceptDrag
     */

    public synchronized void acceptDrag(int dragOperation) {
        if (currentDT == null) {
            throw new InvalidDnDOperationException("No Drag pending");
        }
        currentDA = mapOperation(dragOperation);
        if (currentDA != DnDConstants.ACTION_NONE) {
            dragRejected = false;
        }
    }

    /**
     * rejectDrag
     */

    public synchronized void rejectDrag() {
        if (currentDT == null) {
            throw new InvalidDnDOperationException("No Drag pending");
        }
        currentDA = DnDConstants.ACTION_NONE;
        dragRejected = true;
    }

    /**
     * acceptDrop
     */

    public synchronized void acceptDrop(int dropOperation) {
        if (dropOperation == DnDConstants.ACTION_NONE)
            throw new IllegalArgumentException("invalid acceptDrop() action");

        if (dropStatus != STATUS_WAIT) {
            throw new InvalidDnDOperationException("invalid acceptDrop()");
        }

        currentDA = currentA = mapOperation(dropOperation & currentSA);

        dropStatus   = STATUS_ACCEPT;
        dropComplete = false;
    }

    /**
     * reject Drop
     */

    public synchronized void rejectDrop() {
        if (dropStatus != STATUS_WAIT) {
            throw new InvalidDnDOperationException("invalid rejectDrop()");
        }
        dropStatus = STATUS_REJECT;
        /*
         * Fix for 4285634.
         * The target rejected the drop means that it doesn't perform any
         * drop action. This change is to make Solaris behavior consistent
         * with Win32.
         */
        currentDA = DnDConstants.ACTION_NONE;
        dropComplete(false);
    }

    /**
     * mapOperation
     */

    private int mapOperation(int operation) {
        int[] operations = {
                DnDConstants.ACTION_MOVE,
                DnDConstants.ACTION_COPY,
                DnDConstants.ACTION_LINK,
        };
        int   ret = DnDConstants.ACTION_NONE;

        for (int i = 0; i < operations.length; i++) {
            if ((operation & operations[i]) == operations[i]) {
                    ret = operations[i];
                    break;
            }
        }

        return ret;
    }

    /**
     * signal drop complete
     */

    public synchronized void dropComplete(boolean success) {
        if (dropStatus == STATUS_NONE) {
            throw new InvalidDnDOperationException("No Drop pending");
        }

        if (currentDTC != null) currentDTC.removeNotify();

        currentDT  = null;
        currentDTC = null;
        currentT   = null;
        currentA   = DnDConstants.ACTION_NONE;

        synchronized(_globalLock) {
            currentJVMLocalSourceTransferable = null;
        }

        dropStatus   = STATUS_NONE;
        dropComplete = true;

        try {
            doDropDone(success, currentDA, local != null);
        } finally {
            currentDA = DnDConstants.ACTION_NONE;
            // The native context is invalid after the drop is done.
            // Clear the reference to prohibit access.
            nativeDragContext = 0;
        }
    }

    protected abstract void doDropDone(boolean success,
                                       int dropAction, boolean isLocal);

    protected synchronized long getNativeDragContext() {
        return nativeDragContext;
    }

    protected void eventPosted(SunDropTargetEvent e) {}

    protected void eventProcessed(SunDropTargetEvent e, int returnValue,
                                  boolean dispatcherDone) {}

    protected static class EventDispatcher {

        private final SunDropTargetContextPeer peer;

        // context fields
        private final int dropAction;
        private final int actions;
        private final long[] formats;
        private long nativeCtxt;
        private final boolean dispatchType;
        private boolean dispatcherDone = false;

        // dispatcher state fields
        private int returnValue = 0;
        // set of events to be dispatched by this dispatcher
        private final HashSet eventSet = new HashSet(3);

        static final ToolkitThreadBlockedHandler handler =
            DataTransferer.getInstance().getToolkitThreadBlockedHandler();

        EventDispatcher(SunDropTargetContextPeer peer,
                        int dropAction,
                        int actions,
                        long[] formats,
                        long nativeCtxt,
                        boolean dispatchType) {

            this.peer         = peer;
            this.nativeCtxt   = nativeCtxt;
            this.dropAction   = dropAction;
            this.actions      = actions;
            this.formats =
                     (null == formats) ? null : Arrays.copyOf(formats, formats.length);
            this.dispatchType = dispatchType;
        }

        void dispatchEvent(SunDropTargetEvent e) {
            int id = e.getID();

            switch (id) {
            case SunDropTargetEvent.MOUSE_ENTERED:
                dispatchEnterEvent(e);
                break;
            case SunDropTargetEvent.MOUSE_DRAGGED:
                dispatchMotionEvent(e);
                break;
            case SunDropTargetEvent.MOUSE_EXITED:
                dispatchExitEvent(e);
                break;
            case SunDropTargetEvent.MOUSE_DROPPED:
                dispatchDropEvent(e);
                break;
            default:
                throw new InvalidDnDOperationException();
            }
        }

        private void dispatchEnterEvent(SunDropTargetEvent e) {
            synchronized (peer) {

                // store the drop action here to track operation changes
                peer.previousDA = dropAction;

                // setup peer context
                peer.nativeDragContext = nativeCtxt;
                peer.currentT          = formats;
                peer.currentSA         = actions;
                peer.currentDA         = dropAction;
                // To allow data retrieval.
                peer.dropStatus        = STATUS_ACCEPT;
                peer.dropComplete      = false;

                try {
                    peer.processEnterMessage(e);
                } finally {
                    peer.dropStatus        = STATUS_NONE;
                }

                setReturnValue(peer.currentDA);
            }
        }

        private void dispatchMotionEvent(SunDropTargetEvent e) {
            synchronized (peer) {

                boolean operationChanged = peer.previousDA != dropAction;
                peer.previousDA = dropAction;

                // setup peer context
                peer.nativeDragContext = nativeCtxt;
                peer.currentT          = formats;
                peer.currentSA         = actions;
                peer.currentDA         = dropAction;
                // To allow data retrieval.
                peer.dropStatus        = STATUS_ACCEPT;
                peer.dropComplete      = false;

                try {
                    peer.processMotionMessage(e, operationChanged);
                } finally {
                    peer.dropStatus        = STATUS_NONE;
                }

                setReturnValue(peer.currentDA);
            }
        }

        private void dispatchExitEvent(SunDropTargetEvent e) {
            synchronized (peer) {

                // setup peer context
                peer.nativeDragContext = nativeCtxt;

                peer.processExitMessage(e);
            }
        }

        private void dispatchDropEvent(SunDropTargetEvent e) {
            synchronized (peer) {

                // setup peer context
                peer.nativeDragContext = nativeCtxt;
                peer.currentT          = formats;
                peer.currentSA         = actions;
                peer.currentDA         = dropAction;

                peer.processDropMessage(e);
            }
        }

        void setReturnValue(int ret) {
            returnValue = ret;
        }

        int getReturnValue() {
            return returnValue;
        }

        boolean isDone() {
            return eventSet.isEmpty();
        }

        void registerEvent(SunDropTargetEvent e) {
            handler.lock();
            if (!eventSet.add(e) && dndLog.isLoggable(PlatformLogger.FINE)) {
                dndLog.fine("Event is already registered: " + e);
            }
            handler.unlock();
        }

        void unregisterEvent(SunDropTargetEvent e) {
            handler.lock();
            try {
                if (!eventSet.remove(e)) {
                    // This event has already been unregistered.
                    return;
                }
                if (eventSet.isEmpty()) {
                    if (!dispatcherDone && dispatchType == DISPATCH_SYNC) {
                        handler.exit();
                    }
                    dispatcherDone = true;
                }
            } finally {
                handler.unlock();
            }

            try {
                peer.eventProcessed(e, returnValue, dispatcherDone);
            } finally {
                /*
                 * Clear the reference to the native context if all copies of
                 * the original event are processed.
                 */
                if (dispatcherDone) {
                    nativeCtxt = 0;
                    // Fix for 6342381
                    peer.nativeDragContext = 0;

                }
            }
        }

        public void unregisterAllEvents() {
            Object[] events = null;
            handler.lock();
            try {
                events = eventSet.toArray();
            } finally {
                handler.unlock();
            }

            if (events != null) {
                for (int i = 0; i < events.length; i++) {
                    unregisterEvent((SunDropTargetEvent)events[i]);
                }
            }
        }
    }
}
