/*
 * Copyright 2003-2005 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.awt.X11;

import java.io.IOException;

import java.util.HashMap;

import java.util.logging.*;

/**
 * An abstract class for drop protocols on X11 systems.
 * Contains protocol-independent drop target code.
 *
 * @since 1.5
 */
abstract class XDropTargetProtocol {
    private static final Logger logger =
        Logger.getLogger("sun.awt.X11.xembed.xdnd.XDropTargetProtocol");

    private final XDropTargetProtocolListener listener;

    public static final int EMBEDDER_ALREADY_REGISTERED = 0;

    public static final int UNKNOWN_MESSAGE = 0;
    public static final int ENTER_MESSAGE   = 1;
    public static final int MOTION_MESSAGE  = 2;
    public static final int LEAVE_MESSAGE   = 3;
    public static final int DROP_MESSAGE    = 4;

    protected XDropTargetProtocol(XDropTargetProtocolListener listener) {
        if (listener == null) {
            throw new NullPointerException("Null XDropTargetProtocolListener");
        }
        this.listener = listener;
    }

    protected final XDropTargetProtocolListener getProtocolListener() {
        return listener;
    }

    /**
     * Returns the protocol name. The protocol name cannot be null.
     */
    public abstract String getProtocolName();

    /* The caller must hold AWT_LOCK. */
    public abstract void registerDropTarget(long window);

    /* The caller must hold AWT_LOCK. */
    public abstract void unregisterDropTarget(long window);

    /* The caller must hold AWT_LOCK. */
    public abstract void registerEmbedderDropSite(long window);

    /* The caller must hold AWT_LOCK. */
    public abstract void unregisterEmbedderDropSite(long window);

    /* The caller must hold AWT_LOCK. */
    public abstract void registerEmbeddedDropSite(long embedded);

    /* The caller must hold AWT_LOCK. */
    public final void unregisterEmbeddedDropSite(long embedded) {
        removeEmbedderRegistryEntry(embedded);
    }


    /* The caller must hold AWT_LOCK. */
    public abstract boolean isProtocolSupported(long window);

    public abstract int getMessageType(XClientMessageEvent xclient);

    /* The caller must hold AWT_LOCK. */
    public final boolean processClientMessage(XClientMessageEvent xclient) {
        int type = getMessageType(xclient);
        boolean processed = processClientMessageImpl(xclient);

        postProcessClientMessage(xclient, processed, type);

        return processed;
    }

    /* The caller must hold AWT_LOCK. */
    protected abstract boolean processClientMessageImpl(XClientMessageEvent xclient);

    /*
     * Forwards a drag notification to the embedding toplevel modifying the event
     * to match the protocol version supported by the toplevel.
     * The caller must hold AWT_LOCK.
     * Returns True if the event is sent, False otherwise.
     */
    protected final boolean forwardClientMessageToToplevel(long toplevel,
                                                           XClientMessageEvent xclient) {
        EmbedderRegistryEntry entry = getEmbedderRegistryEntry(toplevel);

        if (logger.isLoggable(Level.FINEST)) {
            logger.log(Level.FINEST, "        entry={0}", new Object[] {entry});
        }
        // Window not registered as an embedder for this protocol.
        if (entry == null) {
            return false;
        }

        if (logger.isLoggable(Level.FINEST)) {
            logger.log(Level.FINEST, "        entry.isOverriden()={0}", new Object[] {entry.isOverriden()});
        }
        // Window didn't have an associated drop site, so there is no need
        // to forward the message.
        if (!entry.isOverriden()) {
            return false;
        }

        adjustEventForForwarding(xclient, entry);

        long proxy = entry.getProxy();

        if (logger.isLoggable(Level.FINEST)) {
            logger.log(Level.FINEST, "        proxy={0} toplevel={1}", new Object[] {proxy, toplevel});
        }
        if (proxy == 0) {
            proxy = toplevel;
        }

        xclient.set_window(toplevel);

        XToolkit.awtLock();
        try {
            XlibWrapper.XSendEvent(XToolkit.getDisplay(), proxy, false,
                                   XlibWrapper.NoEventMask, xclient.pData);
        } finally {
            XToolkit.awtUnlock();
        }

        return true;
    }


    /* True iff the previous notification was MotionEvent and it was
       forwarded to the browser. */
    private boolean motionPassedAlong = false;

    protected abstract void sendEnterMessageToToplevel(long toplevel,
                                                       XClientMessageEvent xclient);

    protected abstract void sendLeaveMessageToToplevel(long toplevel,
                                                       XClientMessageEvent xclient);

    private void postProcessClientMessage(XClientMessageEvent xclient,
                                          boolean processed,
                                          int type) {
        long toplevel = xclient.get_window();

        if (getEmbedderRegistryEntry(toplevel) != null) {
            /*
             * This code forwards drag notifications to the browser according to the
             * following rules:
             *  - the messages that we failed to process are always forwarded to the
             *    browser;
             *  - MotionEvents and DropEvents are forwarded if and only if the drag
             *    is not over a plugin window;
             *  - XDnD: EnterEvents and LeaveEvents are never forwarded, instead, we
             *    send synthesized EnterEvents or LeaveEvents when the drag
             *    respectively exits or enters plugin windows;
             *  - Motif DnD: EnterEvents and LeaveEvents are always forwarded.
             * Synthetic EnterEvents and LeaveEvents are needed, because the XDnD drop
             * site implemented Netscape 6.2 has a nice feature: when it receives
             * the first XdndPosition it continuously sends XdndStatus messages to
             * the source (every 100ms) until the drag terminates or leaves the drop
             * site. When the mouse is dragged over plugin window embedded in the
             * browser frame, these XdndStatus messages are mixed with the XdndStatus
             * messages sent from the plugin.
             * For Motif DnD, synthetic events cause Motif warnings being displayed,
             * so these events are always forwarded. However, Motif DnD drop site in
             * Netscape 6.2 is implemented in the same way, so there could be similar
             * problems if the drag source choose Motif DnD for communication.
             */
            if (!processed) {
                forwardClientMessageToToplevel(toplevel, xclient);
            } else {
                boolean motifProtocol =
                    xclient.get_message_type() ==
                    MotifDnDConstants.XA_MOTIF_DRAG_AND_DROP_MESSAGE.getAtom();

                switch (type) {
                case XDropTargetProtocol.MOTION_MESSAGE:
                    if (!isDragOverComponent()) {
                        if (!motionPassedAlong && !motifProtocol) {
                            sendEnterMessageToToplevel(toplevel, xclient);
                        }
                        forwardClientMessageToToplevel(toplevel, xclient);
                        motionPassedAlong = true;
                    } else {
                        if (motionPassedAlong && !motifProtocol) {
                            sendLeaveMessageToToplevel(toplevel, xclient);
                        }
                        motionPassedAlong = false;
                    }
                    break;
                case XDropTargetProtocol.DROP_MESSAGE:
                    if (!isDragOverComponent()) {
                        forwardClientMessageToToplevel(toplevel, xclient);
                    }
                    motionPassedAlong = false;
                    break;
                case XDropTargetProtocol.ENTER_MESSAGE:
                case XDropTargetProtocol.LEAVE_MESSAGE:
                    if (motifProtocol) {
                        forwardClientMessageToToplevel(toplevel, xclient);
                    }
                    motionPassedAlong = false;
                    break;
                }
            }
        }
    }

    public abstract boolean sendResponse(long ctxt, int eventID, int action);

    /*
     * Retrieves the data from the drag source in the specified format.
     *
     * @param ctxt a pointer to the XClientMessageEvent structure for this
     *             protocol's drop message.
     * @param format the format in which the data should be retrieved.
     *
     * @throws IllegalArgumentException if ctxt doesn't point to the
     *         XClientMessageEvent structure for this protocol's drop message.
     * @throws IOException if data retrieval failed.
     */
    public abstract Object getData(long ctxt, long format)
      throws IllegalArgumentException, IOException;

    public abstract boolean sendDropDone(long ctxt, boolean success,
                                         int dropAction);

    public abstract long getSourceWindow();

    public abstract void cleanup();

    public abstract boolean isDragOverComponent();

    public void adjustEventForForwarding(XClientMessageEvent xclient,
        EmbedderRegistryEntry entry) {}

    public abstract boolean forwardEventToEmbedded(long embedded, long ctxt,
                                                   int eventID);

    /*
     * Returns true if the XEmbed protocol prescribes that an XEmbed server must
     * support this DnD protocol for drop sites associated with XEmbed clients.
     */
    public abstract boolean isXEmbedSupported();

    protected static final class EmbedderRegistryEntry {
        private final boolean overriden;
        private final int version;
        private final long proxy;
        EmbedderRegistryEntry(boolean overriden, int version, long proxy) {
            this.overriden = overriden;
            this.version = version;
            this.proxy = proxy;
        }
        public boolean isOverriden() {
            return overriden;
        }
        public int getVersion() {
            return version;
        }
        public long getProxy() {
            return proxy;
        }
    }

    /* Access to HashMap is synchronized on this XDropTargetProtocol instance. */
    private final HashMap embedderRegistry = new HashMap();

    protected final void putEmbedderRegistryEntry(long embedder,
                                                  boolean overriden,
                                                  int version,
                                                  long proxy) {
        synchronized (this) {
            embedderRegistry.put(Long.valueOf(embedder),
                                 new EmbedderRegistryEntry(overriden, version,
                                                           proxy));
        }
    }

    protected final EmbedderRegistryEntry getEmbedderRegistryEntry(long embedder) {
        synchronized (this) {
            return
                (EmbedderRegistryEntry)embedderRegistry.get(Long.valueOf(embedder));
        }
    }

    protected final void removeEmbedderRegistryEntry(long embedder) {
        synchronized (this) {
            embedderRegistry.remove(new Long(embedder));
        }
    }
}
