/*
 * 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.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import sun.util.logging.PlatformLogger;

import java.awt.Point;


/**
 * The class responsible for registration/deregistration of drop sites.
 *
 * @since 1.5
 */
final class XDropTargetRegistry {
    private static final PlatformLogger logger =
        PlatformLogger.getLogger("sun.awt.X11.xembed.xdnd.XDropTargetRegistry");

    private static final long DELAYED_REGISTRATION_PERIOD = 200;

    private static final XDropTargetRegistry theInstance =
        new XDropTargetRegistry();

    private final HashMap<Long, Runnable> delayedRegistrationMap =
        new HashMap<Long, Runnable>();

    private XDropTargetRegistry() {}

    static XDropTargetRegistry getRegistry() {
        return theInstance;
    }

    /**
     * Returns the XID of the topmost window with WM_STATE set in the ancestor
     * heirarchy of the specified window or 0 if none found.
     */
    private long getToplevelWindow(long window) {
        XBaseWindow candWindow = XToolkit.windowToXWindow(window);
        if (candWindow != null) {
            XWindowPeer toplevel = candWindow.getToplevelXWindow();
            if (toplevel != null && !(toplevel instanceof XEmbeddedFramePeer)) {
                return toplevel.getWindow();
            }
        }

        /* Traverse the ancestor tree from window up to the root and find
           the top-level client window nearest to the root. */
        do {
            if (XlibUtil.isTrueToplevelWindow(window)) {
                return window;
            }

            window = XlibUtil.getParentWindow(window);

        } while (window != 0);

        return window;
    }

    static final long getDnDProxyWindow() {
        return XWindow.getXAWTRootWindow().getWindow();
    }

    private static final class EmbeddedDropSiteEntry {
        private final long root;
        private final long event_mask;
        private List<XDropTargetProtocol> supportedProtocols;
        private final HashSet<Long> nonXEmbedClientSites = new HashSet<Long>();
        private final List<Long> sites = new ArrayList<Long>();

        public EmbeddedDropSiteEntry(long root, long event_mask,
                                     List<XDropTargetProtocol> supportedProtocols) {
            if (supportedProtocols == null) {
                throw new NullPointerException("Null supportedProtocols");
            }
            this.root = root;
            this.event_mask = event_mask;
            this.supportedProtocols = supportedProtocols;
        }

        public long getRoot() {
            return root;
        }
        public long getEventMask() {
            return event_mask;
        }
        public boolean hasNonXEmbedClientSites() {
            return !nonXEmbedClientSites.isEmpty();
        }
        public synchronized void addSite(long window, boolean isXEmbedClient) {
            Long lWindow = Long.valueOf(window);
            if (!sites.contains(lWindow)) {
                sites.add(lWindow);
            }
            if (!isXEmbedClient) {
                nonXEmbedClientSites.add(lWindow);
            }
        }
        public synchronized void removeSite(long window) {
            Long lWindow = Long.valueOf(window);
            sites.remove(lWindow);
            nonXEmbedClientSites.remove(lWindow);
        }
        public void setSupportedProtocols(List<XDropTargetProtocol> list) {
            supportedProtocols = list;
        }
        public List<XDropTargetProtocol> getSupportedProtocols() {
            return supportedProtocols;
        }
        public boolean hasSites() {
            return !sites.isEmpty();
        }
        public long[] getSites() {
            long[] ret = new long[sites.size()];
            Iterator iter = sites.iterator();
            int index = 0;
            while (iter.hasNext()) {
                Long l = (Long)iter.next();
                ret[index++] = l.longValue();
            }
            return ret;
        }
        public long getSite(int x, int y) {
            assert XToolkit.isAWTLockHeldByCurrentThread();

            Iterator<Long> iter = sites.iterator();
            while (iter.hasNext()) {
                Long l = iter.next();
                long window = l.longValue();

                Point p = XBaseWindow.toOtherWindow(getRoot(), window, x, y);

                if (p == null) {
                    continue;
                }

                int dest_x = p.x;
                int dest_y = p.y;
                if (dest_x >= 0 && dest_y >= 0) {
                    XWindowAttributes wattr = new XWindowAttributes();
                    try {
                        XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                        int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                                      window, wattr.pData);
                        XToolkit.RESTORE_XERROR_HANDLER();

                        if (status == 0 ||
                            (XToolkit.saved_error != null &&
                             XToolkit.saved_error.get_error_code() != XConstants.Success)) {
                            continue;
                        }

                        if (wattr.get_map_state() != XConstants.IsUnmapped
                            && dest_x < wattr.get_width()
                            && dest_y < wattr.get_height()) {
                            return window;
                        }
                    } finally {
                        wattr.dispose();
                    }
                }
            }
            return 0;
        }
    }

    private final HashMap<Long, EmbeddedDropSiteEntry> embeddedDropSiteRegistry =
        new HashMap<Long, EmbeddedDropSiteEntry>();

    private EmbeddedDropSiteEntry registerEmbedderDropSite(long embedder) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        Iterator dropTargetProtocols =
            XDragAndDropProtocols.getDropTargetProtocols();
        // The list of protocols supported by the embedder.
        List<XDropTargetProtocol> embedderProtocols = new ArrayList();

        while (dropTargetProtocols.hasNext()) {
            XDropTargetProtocol dropTargetProtocol =
                (XDropTargetProtocol)dropTargetProtocols.next();
            if (dropTargetProtocol.isProtocolSupported(embedder)) {
                embedderProtocols.add(dropTargetProtocol);
            }
        }

        embedderProtocols = Collections.unmodifiableList(embedderProtocols);

        /* Grab server, since we are working with the window that belongs to
           another client. */
        XlibWrapper.XGrabServer(XToolkit.getDisplay());
        try {
            long root = 0;
            long event_mask = 0;
            XWindowAttributes wattr = new XWindowAttributes();
            try {
                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
                                                              embedder, wattr.pData);
                XToolkit.RESTORE_XERROR_HANDLER();

                if (status == 0 ||
                    (XToolkit.saved_error != null &&
                     XToolkit.saved_error.get_error_code() != XConstants.Success)) {
                    throw new XException("XGetWindowAttributes failed");
                }

                event_mask = wattr.get_your_event_mask();
                root = wattr.get_root();
            } finally {
                wattr.dispose();
            }

            if ((event_mask & XConstants.PropertyChangeMask) == 0) {
                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
                                         event_mask | XConstants.PropertyChangeMask);
                XToolkit.RESTORE_XERROR_HANDLER();

                if (XToolkit.saved_error != null &&
                    XToolkit.saved_error.get_error_code() != XConstants.Success) {
                    throw new XException("XSelectInput failed");
                }
            }

            return new EmbeddedDropSiteEntry(root, event_mask, embedderProtocols);
        } finally {
            XlibWrapper.XUngrabServer(XToolkit.getDisplay());
        }
    }

    private static final boolean XEMBED_PROTOCOLS = true;
    private static final boolean NON_XEMBED_PROTOCOLS = false;

    private void registerProtocols(long embedder, boolean protocols,
                                   List<XDropTargetProtocol> supportedProtocols) {
        Iterator dropTargetProtocols = null;

        /*
         * By default, we register a drop site that supports all dnd
         * protocols. This approach is not appropriate in plugin
         * scenario if the browser supports Motif DnD and doesn't support
         * XDnD. If we forcibly set XdndAware on the browser toplevel, any drag
         * source that supports both protocols and prefers XDnD will be unable
         * to drop anything on the browser.
         * The solution for this problem is not to register XDnD drop site
         * if the browser supports only Motif DnD.
         * In general, if the browser already supports some protocols, we
         * register the embedded drop site only for those protocols. Otherwise
         * we register the embedded drop site for all protocols.
         */
        if (!supportedProtocols.isEmpty()) {
            dropTargetProtocols = supportedProtocols.iterator();
        } else {
            dropTargetProtocols =
                XDragAndDropProtocols.getDropTargetProtocols();
        }

        /* Grab server, since we are working with the window that belongs to
           another client. */
        XlibWrapper.XGrabServer(XToolkit.getDisplay());
        try {
            while (dropTargetProtocols.hasNext()) {
                XDropTargetProtocol dropTargetProtocol =
                    (XDropTargetProtocol)dropTargetProtocols.next();
                if ((protocols == XEMBED_PROTOCOLS) ==
                    dropTargetProtocol.isXEmbedSupported()) {
                    dropTargetProtocol.registerEmbedderDropSite(embedder);
                }
            }
        } finally {
            XlibWrapper.XUngrabServer(XToolkit.getDisplay());
        }
    }

    public void updateEmbedderDropSite(long embedder) {
        XBaseWindow xbaseWindow = XToolkit.windowToXWindow(embedder);
        // No need to update our own drop sites.
        if (xbaseWindow != null) {
            return;
        }

        assert XToolkit.isAWTLockHeldByCurrentThread();

        Iterator dropTargetProtocols =
            XDragAndDropProtocols.getDropTargetProtocols();
        // The list of protocols supported by the embedder.
        List<XDropTargetProtocol> embedderProtocols = new ArrayList();

        while (dropTargetProtocols.hasNext()) {
            XDropTargetProtocol dropTargetProtocol =
                (XDropTargetProtocol)dropTargetProtocols.next();
            if (dropTargetProtocol.isProtocolSupported(embedder)) {
                embedderProtocols.add(dropTargetProtocol);
            }
        }

        embedderProtocols = Collections.unmodifiableList(embedderProtocols);

        Long lToplevel = Long.valueOf(embedder);
        boolean isXEmbedServer = false;
        synchronized (this) {
            EmbeddedDropSiteEntry entry =
                (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel);
            if (entry == null) {
                return;
            }
            entry.setSupportedProtocols(embedderProtocols);
            isXEmbedServer = !entry.hasNonXEmbedClientSites();
        }

        /*
         * By default, we register a drop site that supports all dnd
         * protocols. This approach is not appropriate in plugin
         * scenario if the browser supports Motif DnD and doesn't support
         * XDnD. If we forcibly set XdndAware on the browser toplevel, any drag
         * source that supports both protocols and prefers XDnD will be unable
         * to drop anything on the browser.
         * The solution for this problem is not to register XDnD drop site
         * if the browser supports only Motif DnD.
         * In general, if the browser already supports some protocols, we
         * register the embedded drop site only for those protocols. Otherwise
         * we register the embedded drop site for all protocols.
         */
        if (!embedderProtocols.isEmpty()) {
            dropTargetProtocols = embedderProtocols.iterator();
        } else {
            dropTargetProtocols =
                XDragAndDropProtocols.getDropTargetProtocols();
        }

        /* Grab server, since we are working with the window that belongs to
           another client. */
        XlibWrapper.XGrabServer(XToolkit.getDisplay());
        try {
            while (dropTargetProtocols.hasNext()) {
                XDropTargetProtocol dropTargetProtocol =
                    (XDropTargetProtocol)dropTargetProtocols.next();
                if (!isXEmbedServer || !dropTargetProtocol.isXEmbedSupported()) {
                    dropTargetProtocol.registerEmbedderDropSite(embedder);
                }
            }
        } finally {
            XlibWrapper.XUngrabServer(XToolkit.getDisplay());
        }
    }

    private void unregisterEmbedderDropSite(long embedder,
                                            EmbeddedDropSiteEntry entry) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        Iterator dropTargetProtocols =
            XDragAndDropProtocols.getDropTargetProtocols();

        /* Grab server, since we are working with the window that belongs to
           another client. */
        XlibWrapper.XGrabServer(XToolkit.getDisplay());
        try {
            while (dropTargetProtocols.hasNext()) {
                XDropTargetProtocol dropTargetProtocol =
                    (XDropTargetProtocol)dropTargetProtocols.next();
                dropTargetProtocol.unregisterEmbedderDropSite(embedder);
            }

            long event_mask = entry.getEventMask();

            /* Restore the original event mask for the embedder. */
            if ((event_mask & XConstants.PropertyChangeMask) == 0) {
                XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
                XlibWrapper.XSelectInput(XToolkit.getDisplay(), embedder,
                                         event_mask);
                XToolkit.RESTORE_XERROR_HANDLER();

                if (XToolkit.saved_error != null &&
                    XToolkit.saved_error.get_error_code() != XConstants.Success) {
                    throw new XException("XSelectInput failed");
                }
            }
        } finally {
            XlibWrapper.XUngrabServer(XToolkit.getDisplay());
        }
    }

    private void registerEmbeddedDropSite(long toplevel, long window) {
        XBaseWindow xBaseWindow = XToolkit.windowToXWindow(window);
        boolean isXEmbedClient =
            (xBaseWindow instanceof XEmbeddedFramePeer) &&
            ((XEmbeddedFramePeer)xBaseWindow).isXEmbedActive();

        XEmbedCanvasPeer peer = null;
        {
            XBaseWindow xbaseWindow = XToolkit.windowToXWindow(toplevel);
            if (xbaseWindow != null) {
                if (xbaseWindow instanceof XEmbedCanvasPeer) {
                    peer = (XEmbedCanvasPeer)xbaseWindow;
                } else {
                    throw new UnsupportedOperationException();
                }
            }
        }

        Long lToplevel = Long.valueOf(toplevel);
        EmbeddedDropSiteEntry entry = null;
        synchronized (this) {
            entry =
                (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel);
            if (entry == null) {
                if (peer != null) {
                    // Toplevel is an XEmbed server within this VM.
                    // Register an XEmbed drop site.
                    peer.setXEmbedDropTarget();
                    // Create a dummy entry to register the embedded site.
                    entry = new EmbeddedDropSiteEntry(0, 0,
                                                      Collections.<XDropTargetProtocol>emptyList());
                } else {
                    // Foreign toplevel.
                    // Select for PropertyNotify events on the toplevel, so that
                    // we can track changes of the properties relevant to DnD
                    // protocols.
                    entry = registerEmbedderDropSite(toplevel);
                    // Register the toplevel with all DnD protocols that are not
                    // supported by XEmbed - actually setup a proxy, so that
                    // all DnD notifications sent to the toplevel are first
                    // routed to us.
                    registerProtocols(toplevel, NON_XEMBED_PROTOCOLS,
                                      entry.getSupportedProtocols());
                }
                embeddedDropSiteRegistry.put(lToplevel, entry);
            }
        }

        assert entry != null;

        synchronized (entry) {
            // For a foreign toplevel.
            if (peer == null) {
                if (!isXEmbedClient) {
                    // Since this is not an XEmbed client we can no longer rely
                    // on XEmbed to route DnD notifications even for DnD
                    // protocols that are supported by XEmbed.
                    // We rollback to the XEmbed-unfriendly solution - setup
                    // a proxy, so that all DnD notifications sent to the
                    // toplevel are first routed to us.
                    registerProtocols(toplevel, XEMBED_PROTOCOLS,
                                      entry.getSupportedProtocols());
                } else {
                    Iterator dropTargetProtocols =
                        XDragAndDropProtocols.getDropTargetProtocols();

                    // Register the embedded window as a plain drop site with
                    // all DnD protocols that are supported by XEmbed.
                    while (dropTargetProtocols.hasNext()) {
                        XDropTargetProtocol dropTargetProtocol =
                            (XDropTargetProtocol)dropTargetProtocols.next();
                        if (dropTargetProtocol.isXEmbedSupported()) {
                            dropTargetProtocol.registerEmbedderDropSite(window);
                        }
                    }
                }
            }

            entry.addSite(window, isXEmbedClient);
        }
    }

    private void unregisterEmbeddedDropSite(long toplevel, long window) {
        Long lToplevel = Long.valueOf(toplevel);
        EmbeddedDropSiteEntry entry = null;
        synchronized (this) {
            entry =
                (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel);
            if (entry == null) {
                return;
            }
            entry.removeSite(window);
            if (!entry.hasSites()) {
                embeddedDropSiteRegistry.remove(lToplevel);

                XBaseWindow xbaseWindow = XToolkit.windowToXWindow(toplevel);
                if (xbaseWindow != null) {
                    if (xbaseWindow instanceof XEmbedCanvasPeer) {
                        XEmbedCanvasPeer peer = (XEmbedCanvasPeer)xbaseWindow;
                        // Unregister an XEmbed drop site.
                        peer.removeXEmbedDropTarget();
                    } else {
                        throw new UnsupportedOperationException();
                    }
                } else {
                    unregisterEmbedderDropSite(toplevel, entry);
                }
            }
        }
    }

    /*
     * Returns a drop site that is embedded in the specified embedder window and
     * contains the point with the specified root coordinates.
     */
    public long getEmbeddedDropSite(long embedder, int x, int y) {
        Long lToplevel = Long.valueOf(embedder);
        EmbeddedDropSiteEntry entry =
            (EmbeddedDropSiteEntry)embeddedDropSiteRegistry.get(lToplevel);
        if (entry == null) {
            return 0;
        }
        return entry.getSite(x, y);
    }

    /*
     * Note: this method should be called under AWT lock.
     */
    public void registerDropSite(long window) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        if (window == 0) {
            throw new IllegalArgumentException();
        }

        XDropTargetEventProcessor.activate();

        long toplevel = getToplevelWindow(window);

        /*
         * No window with WM_STATE property is found.
         * Since the window can be a plugin window reparented to the browser
         * toplevel, we cannot determine which window will eventually have
         * WM_STATE property set. So we schedule a timer callback that will
         * periodically attempt to find an ancestor with WM_STATE and
         * register the drop site appropriately.
         */
        if (toplevel == 0) {
            addDelayedRegistrationEntry(window);
            return;
        }

        if (toplevel == window) {
            Iterator dropTargetProtocols =
                XDragAndDropProtocols.getDropTargetProtocols();

            while (dropTargetProtocols.hasNext()) {
                XDropTargetProtocol dropTargetProtocol =
                    (XDropTargetProtocol)dropTargetProtocols.next();
                dropTargetProtocol.registerDropTarget(toplevel);
            }
        } else {
            registerEmbeddedDropSite(toplevel, window);
        }
    }

    /*
     * Note: this method should be called under AWT lock.
     */
    public void unregisterDropSite(long window) {
        assert XToolkit.isAWTLockHeldByCurrentThread();

        if (window == 0) {
            throw new IllegalArgumentException();
        }

        long toplevel = getToplevelWindow(window);

        if (toplevel == window) {
            Iterator dropProtocols =
                XDragAndDropProtocols.getDropTargetProtocols();

            removeDelayedRegistrationEntry(window);

            while (dropProtocols.hasNext()) {
                XDropTargetProtocol dropProtocol = (XDropTargetProtocol)dropProtocols.next();
                dropProtocol.unregisterDropTarget(window);
            }
        } else {
            unregisterEmbeddedDropSite(toplevel, window);
        }
    }

    public void registerXEmbedClient(long canvasWindow, long clientWindow) {
        // If the client has an associated XDnD drop site, add a drop target
        // to the XEmbedCanvasPeer's target to route drag notifications to the
        // client.

        XDragSourceProtocol xdndDragProtocol =
            XDragAndDropProtocols.getDragSourceProtocol(XDragAndDropProtocols.XDnD);
        XDragSourceProtocol.TargetWindowInfo info =
            xdndDragProtocol.getTargetWindowInfo(clientWindow);
        if (info != null &&
            info.getProtocolVersion() >= XDnDConstants.XDND_MIN_PROTOCOL_VERSION) {

            if (logger.isLoggable(PlatformLogger.FINE)) {
                logger.fine("        XEmbed drop site will be registered for " + Long.toHexString(clientWindow));
            }
            registerEmbeddedDropSite(canvasWindow, clientWindow);

            Iterator dropTargetProtocols =
                XDragAndDropProtocols.getDropTargetProtocols();

            while (dropTargetProtocols.hasNext()) {
                XDropTargetProtocol dropTargetProtocol =
                    (XDropTargetProtocol)dropTargetProtocols.next();
                dropTargetProtocol.registerEmbeddedDropSite(clientWindow);
            }

            if (logger.isLoggable(PlatformLogger.FINE)) {
                logger.fine("        XEmbed drop site has been registered for " + Long.toHexString(clientWindow));
            }
        }
    }

    public void unregisterXEmbedClient(long canvasWindow, long clientWindow) {
        if (logger.isLoggable(PlatformLogger.FINE)) {
            logger.fine("        XEmbed drop site will be unregistered for " + Long.toHexString(clientWindow));
        }
        Iterator dropTargetProtocols =
            XDragAndDropProtocols.getDropTargetProtocols();

        while (dropTargetProtocols.hasNext()) {
            XDropTargetProtocol dropTargetProtocol =
                (XDropTargetProtocol)dropTargetProtocols.next();
            dropTargetProtocol.unregisterEmbeddedDropSite(clientWindow);
        }

        unregisterEmbeddedDropSite(canvasWindow, clientWindow);

        if (logger.isLoggable(PlatformLogger.FINE)) {
            logger.fine("        XEmbed drop site has beed unregistered for " + Long.toHexString(clientWindow));
        }
    }

    /**************** Delayed drop site registration *******************************/

    private void addDelayedRegistrationEntry(final long window) {
        Long lWindow = Long.valueOf(window);
        Runnable runnable = new Runnable() {
                public void run() {
                    removeDelayedRegistrationEntry(window);
                    registerDropSite(window);
                }
            };

        XToolkit.awtLock();
        try {
            removeDelayedRegistrationEntry(window);
            delayedRegistrationMap.put(lWindow, runnable);
            XToolkit.schedule(runnable, DELAYED_REGISTRATION_PERIOD);
        } finally {
            XToolkit.awtUnlock();
        }
    }

    private void removeDelayedRegistrationEntry(long window) {
        Long lWindow = Long.valueOf(window);

        XToolkit.awtLock();
        try {
            Runnable runnable = delayedRegistrationMap.remove(lWindow);
            if (runnable != null) {
                XToolkit.remove(runnable);
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }
    /*******************************************************************************/
}
