/*
 * Copyright (c) 2003, 2008, 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.X11;

import java.awt.datatransfer.Transferable;

import java.awt.dnd.DnDConstants;
import java.awt.dnd.InvalidDnDOperationException;

import java.util.Map;

import sun.util.logging.PlatformLogger;

import sun.misc.Unsafe;

/**
 * XDragSourceProtocol implementation for XDnD protocol.
 *
 * @since 1.5
 */
class XDnDDragSourceProtocol extends XDragSourceProtocol {
    private static final PlatformLogger logger =
        PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDnDDragSourceProtocol");

    private static final Unsafe unsafe = XlibWrapper.unsafe;

    protected XDnDDragSourceProtocol(XDragSourceProtocolListener listener) {
        super(listener);
    }

    /**
     * Creates an instance associated with the specified listener.
     *
     * @throws NullPointerException if listener is <code>null</code>.
     */
    static XDragSourceProtocol createInstance(XDragSourceProtocolListener listener) {
        return new XDnDDragSourceProtocol(listener);
    }

    public String getProtocolName() {
        return XDragAndDropProtocols.XDnD;
    }

    /**
     * Performs protocol-specific drag initialization.
     *
     * @returns true if the initialized successfully.
     */
    protected void initializeDragImpl(int actions, Transferable contents,
                                         Map formatMap, long[] formats)
      throws InvalidDnDOperationException,
        IllegalArgumentException, XException {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        long window = XDragSourceProtocol.getDragSourceWindow();

        long data = Native.allocateLongArray(3);
        int action_count = 0;
        try {
            if ((actions & DnDConstants.ACTION_COPY) != 0) {
                Native.putLong(data, action_count,
                               XDnDConstants.XA_XdndActionCopy.getAtom());
                action_count++;
            }
            if ((actions & DnDConstants.ACTION_MOVE) != 0) {
                Native.putLong(data, action_count,
                               XDnDConstants.XA_XdndActionMove.getAtom());
                action_count++;
            }
            if ((actions & DnDConstants.ACTION_LINK) != 0) {
                Native.putLong(data, action_count,
                               XDnDConstants.XA_XdndActionLink.getAtom());
                action_count++;
            }

            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
            XDnDConstants.XA_XdndActionList.setAtomData(window,
                                                        XAtom.XA_ATOM,
                                                        data, action_count);
            XToolkit.RESTORE_XERROR_HANDLER();

            if (XToolkit.saved_error != null &&
                XToolkit.saved_error.get_error_code() != XConstants.Success) {
                cleanup();
                throw new XException("Cannot write XdndActionList property");
            }
        } finally {
            unsafe.freeMemory(data);
            data = 0;
        }

        data = Native.allocateLongArray(formats.length);

        try {
            Native.put(data, formats);

            XToolkit.WITH_XERROR_HANDLER(XErrorHandler.VerifyChangePropertyHandler.getInstance());
            XDnDConstants.XA_XdndTypeList.setAtomData(window,
                                                      XAtom.XA_ATOM,
                                                      data, formats.length);
            XToolkit.RESTORE_XERROR_HANDLER();

            if (XToolkit.saved_error != null &&
                XToolkit.saved_error.get_error_code() != XConstants.Success) {
                cleanup();
                throw new XException("Cannot write XdndActionList property");
            }
        } finally {
            unsafe.freeMemory(data);
            data = 0;
        }

        if (!XDnDConstants.XDnDSelection.setOwner(contents, formatMap, formats,
                                                  XConstants.CurrentTime)) {
            cleanup();
            throw new InvalidDnDOperationException("Cannot acquire selection ownership");
        }
    }

    private boolean processXdndStatus(XClientMessageEvent xclient) {
        int action = DnDConstants.ACTION_NONE;

        /* Ignore XDnD messages from all other windows. */
        if (xclient.get_data(0) != getTargetWindow()) {
            return true;
        }

        if ((xclient.get_data(1) & XDnDConstants.XDND_ACCEPT_DROP_FLAG) != 0) {
            /* This feature is new in XDnD version 2, but we can use it as XDnD
               compliance only requires supporting version 3 and up. */
            action = XDnDConstants.getJavaActionForXDnDAction(xclient.get_data(4));
        }

        getProtocolListener().handleDragReply(action);

        return true;
    }

    private boolean processXdndFinished(XClientMessageEvent xclient) {
        /* Ignore XDnD messages from all other windows. */
        if (xclient.get_data(0) != getTargetWindow()) {
            return true;
        }

        if (getTargetProtocolVersion() >= 5) {
            boolean success = (xclient.get_data(1) & XDnDConstants.XDND_ACCEPT_DROP_FLAG) != 0;
            int action = XDnDConstants.getJavaActionForXDnDAction(xclient.get_data(2));
            getProtocolListener().handleDragFinished(success, action);
        } else {
            getProtocolListener().handleDragFinished();
        }

        finalizeDrop();

        return true;
    }

    public boolean processClientMessage(XClientMessageEvent xclient) {
        if (xclient.get_message_type() == XDnDConstants.XA_XdndStatus.getAtom()) {
            return processXdndStatus(xclient);
        } else if (xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {
            return processXdndFinished(xclient);
        } else {
            return false;
        }
    }

    public TargetWindowInfo getTargetWindowInfo(long window) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        WindowPropertyGetter wpg1 =
            new WindowPropertyGetter(window, XDnDConstants.XA_XdndAware, 0, 1,
                                     false, XConstants.AnyPropertyType);

        int status = wpg1.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

        if (status == XConstants.Success &&
            wpg1.getData() != 0 && wpg1.getActualType() == XAtom.XA_ATOM) {

            int targetVersion = (int)Native.getLong(wpg1.getData());

            wpg1.dispose();

            if (targetVersion >= XDnDConstants.XDND_MIN_PROTOCOL_VERSION) {
                long proxy = 0;
                int protocolVersion =
                    targetVersion < XDnDConstants.XDND_PROTOCOL_VERSION ?
                    targetVersion : XDnDConstants.XDND_PROTOCOL_VERSION;

                WindowPropertyGetter wpg2 =
                    new WindowPropertyGetter(window, XDnDConstants.XA_XdndProxy,
                                             0, 1, false, XAtom.XA_WINDOW);

                try {
                    status = wpg2.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

                    if (status == XConstants.Success &&
                        wpg2.getData() != 0 &&
                        wpg2.getActualType() == XAtom.XA_WINDOW) {

                        proxy = Native.getLong(wpg2.getData());
                    }
                } finally {
                    wpg2.dispose();
                }

                if (proxy != 0) {
                    WindowPropertyGetter wpg3 =
                        new WindowPropertyGetter(proxy, XDnDConstants.XA_XdndProxy,
                                                 0, 1, false, XAtom.XA_WINDOW);

                    try {
                        status = wpg3.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

                        if (status != XConstants.Success ||
                            wpg3.getData() == 0 ||
                            wpg3.getActualType() != XAtom.XA_WINDOW ||
                            Native.getLong(wpg3.getData()) != proxy) {

                            proxy = 0;
                        } else {
                            WindowPropertyGetter wpg4 =
                                new WindowPropertyGetter(proxy,
                                                         XDnDConstants.XA_XdndAware,
                                                         0, 1, false,
                                                         XConstants.AnyPropertyType);

                            try {
                                status = wpg4.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance());

                                if (status != XConstants.Success ||
                                    wpg4.getData() == 0 ||
                                    wpg4.getActualType() != XAtom.XA_ATOM) {

                                    proxy = 0;
                                }
                            } finally {
                                wpg4.dispose();
                            }
                        }
                    } finally {
                        wpg3.dispose();
                    }
                }

                return new TargetWindowInfo(proxy, protocolVersion);
            }
        } else {
            wpg1.dispose();
        }

        return null;
    }

    public void sendEnterMessage(long[] formats,
                                 int sourceAction, int sourceActions, long time) {
        assert XToolkit.isAWTLockHeldByCurrentThread();
        assert getTargetWindow() != 0;
        assert formats != null;

        XClientMessageEvent msg = new XClientMessageEvent();
        try {
            msg.set_type((int)XConstants.ClientMessage);
            msg.set_window(getTargetWindow());
            msg.set_format(32);
            msg.set_message_type(XDnDConstants.XA_XdndEnter.getAtom());
            msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
            long data1 =
                getTargetProtocolVersion() << XDnDConstants.XDND_PROTOCOL_SHIFT;
            data1 |= formats.length > 3 ? XDnDConstants.XDND_DATA_TYPES_BIT : 0;
            msg.set_data(1, data1);
            msg.set_data(2, formats.length > 0 ? formats[0] : 0);
            msg.set_data(3, formats.length > 1 ? formats[1] : 0);
            msg.set_data(4, formats.length > 2 ? formats[2] : 0);
            XlibWrapper.XSendEvent(XToolkit.getDisplay(),
                                   getTargetProxyWindow(),
                                   false, XConstants.NoEventMask,
                                   msg.pData);
        } finally {
            msg.dispose();
        }
    }

    public void sendMoveMessage(int xRoot, int yRoot,
                                int sourceAction, int sourceActions, long time) {
        assert XToolkit.isAWTLockHeldByCurrentThread();
        assert getTargetWindow() != 0;

        XClientMessageEvent msg = new XClientMessageEvent();
        try {
            msg.set_type((int)XConstants.ClientMessage);
            msg.set_window(getTargetWindow());
            msg.set_format(32);
            msg.set_message_type(XDnDConstants.XA_XdndPosition.getAtom());
            msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
            msg.set_data(1, 0); /* flags */
            msg.set_data(2, xRoot << 16 | yRoot);
            msg.set_data(3, time);
            msg.set_data(4, XDnDConstants.getXDnDActionForJavaAction(sourceAction));
            XlibWrapper.XSendEvent(XToolkit.getDisplay(),
                                   getTargetProxyWindow(),
                                   false, XConstants.NoEventMask,
                                   msg.pData);
        } finally {
            msg.dispose();
        }
    }

    public void sendLeaveMessage(long time) {
        assert XToolkit.isAWTLockHeldByCurrentThread();
        assert getTargetWindow() != 0;

        XClientMessageEvent msg = new XClientMessageEvent();
        try {
            msg.set_type((int)XConstants.ClientMessage);
            msg.set_window(getTargetWindow());
            msg.set_format(32);
            msg.set_message_type(XDnDConstants.XA_XdndLeave.getAtom());
            msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
            msg.set_data(1, 0);
            msg.set_data(2, 0);
            msg.set_data(3, 0);
            msg.set_data(4, 0);
            XlibWrapper.XSendEvent(XToolkit.getDisplay(),
                                   getTargetProxyWindow(),
                                   false, XConstants.NoEventMask,
                                   msg.pData);
        } finally {
            msg.dispose();
        }
    }

    public void sendDropMessage(int xRoot, int yRoot,
                                int sourceAction, int sourceActions,
                                long time) {
        assert XToolkit.isAWTLockHeldByCurrentThread();
        assert getTargetWindow() != 0;

        XClientMessageEvent msg = new XClientMessageEvent();
        try {
            msg.set_type((int)XConstants.ClientMessage);
            msg.set_window(getTargetWindow());
            msg.set_format(32);
            msg.set_message_type(XDnDConstants.XA_XdndDrop.getAtom());
            msg.set_data(0, XDragSourceProtocol.getDragSourceWindow());
            msg.set_data(1, 0); /* flags */
            msg.set_data(2, time);
            msg.set_data(3, 0);
            msg.set_data(4, 0);
            XlibWrapper.XSendEvent(XToolkit.getDisplay(),
                                   getTargetProxyWindow(),
                                   false, XConstants.NoEventMask,
                                   msg.pData);
        } finally {
            msg.dispose();
        }
    }

    public boolean processProxyModeEvent(XClientMessageEvent xclient,
                                         long sourceWindow) {
        if (xclient.get_message_type() == XDnDConstants.XA_XdndStatus.getAtom() ||
            xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {

            if (xclient.get_message_type() == XDnDConstants.XA_XdndFinished.getAtom()) {
                XDragSourceContextPeer.setProxyModeSourceWindow(0);
            }

            // This can happen if the drag operation started in the XEmbed server.
            // In this case there is no need to forward it elsewhere, we should
            // process it here.
            if (xclient.get_window() == sourceWindow) {
                return false;
            }

            if (logger.isLoggable(PlatformLogger.FINEST)) {
                logger.finest("        sourceWindow=" + sourceWindow +
                              " get_window=" + xclient.get_window() +
                              " xclient=" + xclient);
            }
            xclient.set_data(0, xclient.get_window());
            xclient.set_window(sourceWindow);

            assert XToolkit.isAWTLockHeldByCurrentThread();

            XlibWrapper.XSendEvent(XToolkit.getDisplay(), sourceWindow,
                                   false, XConstants.NoEventMask,
                                   xclient.pData);

            return true;
        }

        return false;
    }

    // TODO: register this runnable with XDnDSelection.
    public void run() {
        // XdndSelection ownership lost.
        cleanup();
    }
}
