/*
 * Copyright 1999-2006 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.datatransfer;

import java.awt.EventQueue;

import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.FlavorTable;
import java.awt.datatransfer.SystemFlavorMap;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorListener;
import java.awt.datatransfer.FlavorEvent;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import java.util.Iterator;
import java.util.Set;
import java.util.HashSet;

import java.io.IOException;

import sun.awt.AppContext;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
import sun.awt.EventListenerAggregate;


/**
 * Serves as a common, helper superclass for the Win32 and X11 system
 * Clipboards.
 *
 * @author Danila Sinopalnikov
 * @author Alexander Gerasimov
 *
 * @since 1.3
 */
public abstract class SunClipboard extends Clipboard
    implements PropertyChangeListener {

    public static final FlavorTable flavorMap =
        (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();

    private AppContext contentsContext = null;

    private final Object CLIPBOARD_FLAVOR_LISTENER_KEY;

    /**
     * A number of <code>FlavorListener</code>s currently registered
     * on this clipboard across all <code>AppContext</code>s.
     */
    private volatile int numberOfFlavorListeners = 0;

    /**
     * A set of <code>DataFlavor</code>s that is available on
     * this clipboard. It is used for tracking changes
     * of <code>DataFlavor</code>s available on this clipboard.
     */
    private volatile Set currentDataFlavors;


    public SunClipboard(String name) {
        super(name);
        CLIPBOARD_FLAVOR_LISTENER_KEY = new StringBuffer(name + "_CLIPBOARD_FLAVOR_LISTENER_KEY");
    }

    public synchronized void setContents(Transferable contents,
                                         ClipboardOwner owner) {
        // 4378007 : Toolkit.getSystemClipboard().setContents(null, null)
        // should throw NPE
        if (contents == null) {
            throw new NullPointerException("contents");
        }

        initContext();

        final ClipboardOwner oldOwner = this.owner;
        final Transferable oldContents = this.contents;

        try {
            this.owner = owner;
            this.contents = new TransferableProxy(contents, true);

            setContentsNative(contents);
        } finally {
            if (oldOwner != null && oldOwner != owner) {
                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        oldOwner.lostOwnership(SunClipboard.this, oldContents);
                    }
                });
            }
        }
    }

    private synchronized void initContext() {
        final AppContext context = AppContext.getAppContext();

        if (contentsContext != context) {
            // Need to synchronize on the AppContext to guarantee that it cannot
            // be disposed after the check, but before the listener is added.
            synchronized (context) {
                if (context.isDisposed()) {
                    throw new IllegalStateException("Can't set contents from disposed AppContext");
                }
                context.addPropertyChangeListener
                    (AppContext.DISPOSED_PROPERTY_NAME, this);
            }
            if (contentsContext != null) {
                contentsContext.removePropertyChangeListener
                    (AppContext.DISPOSED_PROPERTY_NAME, this);
            }
            contentsContext = context;
        }
    }

    public synchronized Transferable getContents(Object requestor) {
        if (contents != null) {
            return contents;
        }
        return new ClipboardTransferable(this);
    }


    /**
     * @return the contents of this clipboard if it has been set from the same
     *         AppContext as it is currently retrieved or null otherwise
     * @since 1.5
     */
    private synchronized Transferable getContextContents() {
        AppContext context = AppContext.getAppContext();
        return (context == contentsContext) ? contents : null;
    }


    /**
     * @see java.awt.Clipboard#getAvailableDataFlavors
     * @since 1.5
     */
    public DataFlavor[] getAvailableDataFlavors() {
        Transferable cntnts = getContextContents();
        if (cntnts != null) {
            return cntnts.getTransferDataFlavors();
        }

        long[] formats = getClipboardFormatsOpenClose();

        return DataTransferer.getInstance().
            getFlavorsForFormatsAsArray(formats, flavorMap);
    }

    /**
     * @see java.awt.Clipboard#isDataFlavorAvailable
     * @since 1.5
     */
    public boolean isDataFlavorAvailable(DataFlavor flavor) {
        if (flavor == null) {
            throw new NullPointerException("flavor");
        }

        Transferable cntnts = getContextContents();
        if (cntnts != null) {
            return cntnts.isDataFlavorSupported(flavor);
        }

        long[] formats = getClipboardFormatsOpenClose();

        return formatArrayAsDataFlavorSet(formats).contains(flavor);
    }

    /**
     * @see java.awt.Clipboard#getData
     * @since 1.5
     */
    public Object getData(DataFlavor flavor)
        throws UnsupportedFlavorException, IOException {
        if (flavor == null) {
            throw new NullPointerException("flavor");
        }

        Transferable cntnts = getContextContents();
        if (cntnts != null) {
            return cntnts.getTransferData(flavor);
        }

        long format = 0;
        byte[] data = null;
        Transferable localeTransferable = null;

        try {
            openClipboard(null);

            long[] formats = getClipboardFormats();
            Long lFormat = (Long)DataTransferer.getInstance().
                    getFlavorsForFormats(formats, flavorMap).get(flavor);

            if (lFormat == null) {
                throw new UnsupportedFlavorException(flavor);
            }

            format = lFormat.longValue();
            data = getClipboardData(format);

            if (DataTransferer.getInstance().isLocaleDependentTextFormat(format)) {
                localeTransferable = createLocaleTransferable(formats);
            }

        } finally {
            closeClipboard();
        }

        return DataTransferer.getInstance().
                translateBytes(data, flavor, format, localeTransferable);
    }

    /**
     * The clipboard must be opened.
     *
     * @since 1.5
     */
    protected Transferable createLocaleTransferable(long[] formats) throws IOException {
        return null;
    }

    /**
     * @throws IllegalStateException if the clipboard has not been opened
     */
    public void openClipboard(SunClipboard newOwner) {}
    public void closeClipboard() {}

    public abstract long getID();

    public void propertyChange(PropertyChangeEvent evt) {
        if (AppContext.DISPOSED_PROPERTY_NAME.equals(evt.getPropertyName()) &&
            Boolean.TRUE.equals(evt.getNewValue())) {
            final AppContext disposedContext = (AppContext)evt.getSource();
            lostOwnershipLater(disposedContext);
        }
    }

    protected void lostOwnershipImpl() {
        lostOwnershipLater(null);
    }

    /**
     * Clears the clipboard state (contents, owner and contents context) and
     * notifies the current owner that ownership is lost. Does nothing if the
     * argument is not <code>null</code> and is not equal to the current
     * contents context.
     *
     * @param disposedContext the AppContext that is disposed or
     *        <code>null</code> if the ownership is lost because another
     *        application acquired ownership.
     */
    protected void lostOwnershipLater(final AppContext disposedContext) {
        final AppContext context = this.contentsContext;
        if (context == null) {
            return;
        }

        final Runnable runnable = new Runnable() {
                public void run() {
                    final SunClipboard sunClipboard = SunClipboard.this;
                    ClipboardOwner owner = null;
                    Transferable contents = null;

                    synchronized (sunClipboard) {
                        final AppContext context = sunClipboard.contentsContext;

                        if (context == null) {
                            return;
                        }

                        if (disposedContext == null || context == disposedContext) {
                            owner = sunClipboard.owner;
                            contents = sunClipboard.contents;
                            sunClipboard.contentsContext = null;
                            sunClipboard.owner = null;
                            sunClipboard.contents = null;
                            sunClipboard.clearNativeContext();
                            context.removePropertyChangeListener
                                (AppContext.DISPOSED_PROPERTY_NAME, sunClipboard);
                        } else {
                            return;
                        }
                    }
                    if (owner != null) {
                        owner.lostOwnership(sunClipboard, contents);
                    }
                }
            };

        SunToolkit.postEvent(context, new PeerEvent(this, runnable,
                                                    PeerEvent.PRIORITY_EVENT));
    }

    protected abstract void clearNativeContext();

    protected abstract void setContentsNative(Transferable contents);

    /**
     * @since 1.5
     */
    protected long[] getClipboardFormatsOpenClose() {
        try {
            openClipboard(null);
            return getClipboardFormats();
        } finally {
            closeClipboard();
        }
    }

    /**
     * Returns zero-length array (not null) if the number of available formats is zero.
     *
     * @throws IllegalStateException if formats could not be retrieved
     */
    protected abstract long[] getClipboardFormats();

    protected abstract byte[] getClipboardData(long format) throws IOException;


    private static Set formatArrayAsDataFlavorSet(long[] formats) {
        return (formats == null) ? null :
                DataTransferer.getInstance().
                getFlavorsForFormatsAsSet(formats, flavorMap);
    }


    public synchronized void addFlavorListener(FlavorListener listener) {
        if (listener == null) {
            return;
        }
        AppContext appContext = AppContext.getAppContext();
        EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
                appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
        if (contextFlavorListeners == null) {
            contextFlavorListeners = new EventListenerAggregate(FlavorListener.class);
            appContext.put(CLIPBOARD_FLAVOR_LISTENER_KEY, contextFlavorListeners);
        }
        contextFlavorListeners.add(listener);

        if (numberOfFlavorListeners++ == 0) {
            long[] currentFormats = null;
            try {
                openClipboard(null);
                currentFormats = getClipboardFormats();
            } catch (IllegalStateException exc) {
            } finally {
                closeClipboard();
            }
            currentDataFlavors = formatArrayAsDataFlavorSet(currentFormats);

            registerClipboardViewerChecked();
        }
    }

    public synchronized void removeFlavorListener(FlavorListener listener) {
        if (listener == null) {
            return;
        }
        AppContext appContext = AppContext.getAppContext();
        EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
                appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
        if (contextFlavorListeners == null){
            //else we throw NullPointerException, but it is forbidden
            return;
        }
        if (contextFlavorListeners.remove(listener) &&
                --numberOfFlavorListeners == 0) {
            unregisterClipboardViewerChecked();
            currentDataFlavors = null;
        }
    }

    public synchronized FlavorListener[] getFlavorListeners() {
        EventListenerAggregate contextFlavorListeners = (EventListenerAggregate)
                AppContext.getAppContext().get(CLIPBOARD_FLAVOR_LISTENER_KEY);
        return contextFlavorListeners == null ? new FlavorListener[0] :
                (FlavorListener[])contextFlavorListeners.getListenersCopy();
    }

    public boolean areFlavorListenersRegistered() {
        return (numberOfFlavorListeners > 0);
    }

    protected abstract void registerClipboardViewerChecked();

    protected abstract void unregisterClipboardViewerChecked();

    /**
     * Checks change of the <code>DataFlavor</code>s and, if necessary,
     * posts notifications on <code>FlavorEvent</code>s to the
     * AppContexts' EDTs.
     * The parameter <code>formats</code> is null iff we have just
     * failed to get formats available on the clipboard.
     *
     * @param formats data formats that have just been retrieved from
     *        this clipboard
     */
    public void checkChange(long[] formats) {
        Set prevDataFlavors = currentDataFlavors;
        currentDataFlavors = formatArrayAsDataFlavorSet(formats);

        if ((prevDataFlavors != null) && (currentDataFlavors != null) &&
                prevDataFlavors.equals(currentDataFlavors)) {
            // we've been able to successfully get available on the clipboard
            // DataFlavors this and previous time and they are coincident;
            // don't notify
            return;
        }

        class SunFlavorChangeNotifier implements Runnable {
            private final FlavorListener flavorListener;

            SunFlavorChangeNotifier(FlavorListener flavorListener) {
                this.flavorListener = flavorListener;
            }

            public void run() {
                if (flavorListener != null) {
                    flavorListener.flavorsChanged(new FlavorEvent(SunClipboard.this));
                }
            }
        };

        for (Iterator it = AppContext.getAppContexts().iterator(); it.hasNext();) {
            AppContext appContext = (AppContext)it.next();
            if (appContext == null || appContext.isDisposed()) {
                continue;
            }
            EventListenerAggregate flavorListeners = (EventListenerAggregate)
                    appContext.get(CLIPBOARD_FLAVOR_LISTENER_KEY);
            if (flavorListeners != null) {
                FlavorListener[] flavorListenerArray =
                        (FlavorListener[])flavorListeners.getListenersInternal();
                for (int i = 0; i < flavorListenerArray.length; i++) {
                    SunToolkit.postEvent(appContext, new PeerEvent(this,
                            new SunFlavorChangeNotifier(flavorListenerArray[i]),
                            PeerEvent.PRIORITY_EVENT));
                }
            }
        }
    }

}
