/*
 * 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.
 */

 /*
   * This code is ported to XAWT from MAWT based on awt_mgrsel.c
   * code written originally by Valeriy Ushakov
   * Author : Bino George
   */

package sun.awt.X11;

import java.util.*;
import sun.util.logging.PlatformLogger;

public class  XMSelection {

    /*
     * A method for a subsytem to express its interest in a certain
     * manager selection.
     *
     * If owner changes, the ownerChanged of the XMSelectionListener
     * will be called with the screen
     * number and the new owning window when onwership is established, or
     * None if the owner is gone.
     *
     * Events in extra_mask are selected for on owning windows (exsiting
     * ones and on new owners when established) and otherEvent of the
     * XMWSelectionListener will be called with the screen number and an event.
     *
     * The function returns an array of current owners.  The size of the
     * array is ScreenCount(awt_display).  The array is "owned" by this
     * module and should be considered by the caller as read-only.
     */


    private static PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XMSelection");
    /* Name of the selection */
    String selectionName;

    /* list of listeners to be called for events */
    Vector listeners;

    /* X atom array (one per screen) for this selection */
    XAtom atoms[];

    /* Window ids of selection owners */
    long owners[];

    /* event mask to set */
    long eventMask;

    static int numScreens;

    static XAtom XA_MANAGER;

    static HashMap selectionMap;

    static {
        long display = XToolkit.getDisplay();
        XToolkit.awtLock();
        try {
            numScreens = XlibWrapper.ScreenCount(display);
        } finally {
            XToolkit.awtUnlock();
        }
        XA_MANAGER = XAtom.get("MANAGER");
        for (int screen = 0; screen < numScreens ; screen ++) {
            initScreen(display,screen);
        }

        selectionMap = new HashMap();
    }

    static void initScreen(long display, final int screen) {
        XToolkit.awtLock();
        try {
            long root = XlibWrapper.RootWindow(display,screen);
            XlibWrapper.XSelectInput(display, root, XConstants.StructureNotifyMask);
            XToolkit.addEventDispatcher(root,
                    new XEventDispatcher() {
                        public void dispatchEvent(XEvent ev) {
                                processRootEvent(ev, screen);
                            }
                        });

        } finally {
            XToolkit.awtUnlock();
        }
    }


    public int getNumberOfScreens() {
        return numScreens;
    }

    void select(long extra_mask) {
        eventMask = extra_mask;
        for (int screen = 0; screen < numScreens ; screen ++) {
            selectPerScreen(screen,extra_mask);
        }
    }

    void resetOwner(long owner, final int screen) {
        XToolkit.awtLock();
        try {
            long display = XToolkit.getDisplay();
            synchronized(this) {
                setOwner(owner, screen);
                if (log.isLoggable(PlatformLogger.FINE)) log.fine("New Selection Owner for screen " + screen + " = " + owner );
                XlibWrapper.XSelectInput(display, owner, XConstants.StructureNotifyMask | eventMask);
                XToolkit.addEventDispatcher(owner,
                        new XEventDispatcher() {
                            public void dispatchEvent(XEvent ev) {
                                dispatchSelectionEvent(ev, screen);
                            }
                        });

            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    void selectPerScreen(final int screen, long extra_mask) {
        XToolkit.awtLock();
        try {
            try {
                long display = XToolkit.getDisplay();
                if (log.isLoggable(PlatformLogger.FINE)) log.fine("Grabbing XServer");
                XlibWrapper.XGrabServer(display);

                synchronized(this) {
                    String selection_name = getName()+"_S"+screen;
                    if (log.isLoggable(PlatformLogger.FINE)) log.fine("Screen = " + screen + " selection name = " + selection_name);
                    XAtom atom = XAtom.get(selection_name);
                    selectionMap.put(Long.valueOf(atom.getAtom()),this); // add mapping from atom to the instance of XMSelection
                    setAtom(atom,screen);
                    long owner = XlibWrapper.XGetSelectionOwner(display, atom.getAtom());
                    if (owner != 0) {
                        setOwner(owner, screen);
                        if (log.isLoggable(PlatformLogger.FINE)) log.fine("Selection Owner for screen " + screen + " = " + owner );
                        XlibWrapper.XSelectInput(display, owner, XConstants.StructureNotifyMask | extra_mask);
                        XToolkit.addEventDispatcher(owner,
                                new XEventDispatcher() {
                                        public void dispatchEvent(XEvent ev) {
                                            dispatchSelectionEvent(ev, screen);
                                        }
                                    });
                    }
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                if (log.isLoggable(PlatformLogger.FINE)) log.fine("UnGrabbing XServer");
                XlibWrapper.XUngrabServer(XToolkit.getDisplay());
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }


    static boolean processClientMessage(XEvent xev, int screen) {
        XClientMessageEvent xce = xev.get_xclient();
        if (xce.get_message_type() == XA_MANAGER.getAtom()) {
            if (log.isLoggable(PlatformLogger.FINE)) log.fine("client messags = " + xce);
            long timestamp = xce.get_data(0);
            long atom = xce.get_data(1);
            long owner = xce.get_data(2);
            long data = xce.get_data(3);

            XMSelection sel = getInstance(atom);
            if (sel != null) {
                sel.resetOwner(owner,screen);
                sel.dispatchOwnerChangedEvent(xev,screen,owner,data, timestamp);
            }
        }
        return false;
    }

    static  boolean processRootEvent(XEvent xev, int screen) {
        switch (xev.get_type()) {
            case XConstants.ClientMessage: {
                return processClientMessage(xev, screen);
            }
        }

        return false;

    }


    static XMSelection getInstance(long selection) {
        return (XMSelection) selectionMap.get(Long.valueOf(selection));
    }


    /*
     * Default constructor specifies PropertyChangeMask as well
     */

    public XMSelection (String selname) {
        this(selname, XConstants.PropertyChangeMask);
    }


   /*
    * Some users may not need to know about selection changes,
    * just owner ship changes, They would specify a zero extra mask.
    */

    public XMSelection (String selname, long extraMask) {

        synchronized (this) {
            selectionName = selname;
            atoms = new XAtom[getNumberOfScreens()];
            owners = new long[getNumberOfScreens()];
        }
        select(extraMask);
    }



    public synchronized void addSelectionListener(XMSelectionListener listener) {
        if (listeners == null) {
            listeners = new Vector();
        }
        listeners.add(listener);
    }

    public synchronized void removeSelectionListener(XMSelectionListener listener) {
        if (listeners != null) {
            listeners.remove(listener);
        }
    }

    synchronized Collection getListeners() {
        return listeners;
    }

    synchronized XAtom getAtom(int screen) {
        if (atoms != null) {
            return atoms[screen];
        }
        return null;
    }

    synchronized void setAtom(XAtom a, int screen) {
        if (atoms != null) {
            atoms[screen] = a;
        }
    }

    synchronized long getOwner(int screen) {
        if (owners != null) {
            return owners[screen];
        }
        return 0;
    }

    synchronized void setOwner(long owner, int screen) {
        if (owners != null) {
            owners[screen] = owner;
        }
    }

    synchronized String getName() {
        return selectionName;
    }


    synchronized void dispatchSelectionChanged( XPropertyEvent ev, int screen) {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("Selection Changed : Screen = " + screen + "Event =" + ev);
        if (listeners != null) {
            Iterator iter = listeners.iterator();
            while (iter.hasNext()) {
                XMSelectionListener disp = (XMSelectionListener) iter.next();
                disp.selectionChanged(screen, this, ev.get_window(), ev);
            }
        }
    }

    synchronized void dispatchOwnerDeath(XDestroyWindowEvent de, int screen) {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("Owner dead : Screen = " + screen + "Event =" + de);
        if (listeners != null) {
            Iterator iter = listeners.iterator();
            while (iter.hasNext()) {
                XMSelectionListener disp = (XMSelectionListener) iter.next();
                disp.ownerDeath(screen, this, de.get_window());

            }
        }
    }

    void dispatchSelectionEvent(XEvent xev, int screen) {
        if (log.isLoggable(PlatformLogger.FINE)) log.fine("Event =" + xev);
        if (xev.get_type() == XConstants.DestroyNotify) {
            XDestroyWindowEvent de = xev.get_xdestroywindow();
            dispatchOwnerDeath( de, screen);
        }
        else if (xev.get_type() == XConstants.PropertyNotify)  {
            XPropertyEvent xpe = xev.get_xproperty();
            dispatchSelectionChanged( xpe, screen);
        }
    }


    synchronized void dispatchOwnerChangedEvent(XEvent ev, int screen, long owner, long data, long timestamp) {
        if (listeners != null) {
            Iterator iter = listeners.iterator();
            while (iter.hasNext()) {
                XMSelectionListener disp = (XMSelectionListener) iter.next();
                disp.ownerChanged(screen,this, owner, data, timestamp);
            }
        }
    }


}
