/**
 *  Licensed under GPL. For more information, see
 *    http://jaxodraw.sourceforge.net/license.html
 *  or the LICENSE file in the jaxodraw distribution.
 */

package net.sf.jaxodraw.gui;

import java.awt.Component;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.io.IOException;

import net.sf.jaxodraw.graph.JaxoGraph;
import net.sf.jaxodraw.util.JaxoLog;

/**
 * A Clipboard for JaxoGraphs.
 */
public class JaxoClipboard {
    private static final DataFlavor GRAPH_FLAVOR =
        new DataFlavor("application/x-jaxodraw-graph;class="
            + JaxoGraph.class.getName() + ";version=2", "JaxoDraw graph");

    private transient Clipboard fakeSystemClipboard;
    private final Component parentC;

    /**
     * Constructor.
     *
     * @param parent the parent component. Not null.
     */
    public JaxoClipboard(final Component parent) {
        this.parentC = parent;
    }

    /**
     * Check if the system clipboard contains a JaxoGraph.
     *
     * @return true if the system clipboard contains a JaxoGraph, false otherwise.
     */
    protected boolean canPasteGraphFromSystemClipboard() {
        final Clipboard c = getSystemClipboard();

        try {
            return c.isDataFlavorAvailable(GRAPH_FLAVOR);
        } catch (IllegalStateException e) {
            JaxoLog.debug(e);
            return false;
        }
    }

    /**
     * Graph on the system clipboard.
     *
     * @return the current graph on the system clipboard, or null if none.
     */
    protected JaxoGraph getSystemClipboardGraph() {
        final Clipboard c = getSystemClipboard();

        try {
            final Transferable t = c.getContents(this);

            return (JaxoGraph) t.getTransferData(GRAPH_FLAVOR);
        } catch (IllegalStateException e) {
            systemClipboardUnavailable();
            return null;
        } catch (UnsupportedFlavorException e) {
            return null;
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * Make 'g' the contents of the system clipboard.
     *
     * @param g the graph to put on the clipboard.
     */
    protected void putToSystemClipboard(final JaxoGraph g) {
        final JaxoGraph graph = g.copyOf();

        final Transferable t = new ClipboardTransferable(graph);

        try {
            getSystemClipboard().setContents(t, null);
        } catch (IllegalStateException e) {
            JaxoLog.debug(e);
            systemClipboardUnavailable();
        }
    }

    private static class ClipboardTransferable implements Transferable {
        private final JaxoGraph jaxoGraph;

        ClipboardTransferable(final JaxoGraph graph) {
            this.jaxoGraph = graph;
        }

        public DataFlavor[] getTransferDataFlavors() {
            return new DataFlavor[]{GRAPH_FLAVOR};
        }

        public boolean isDataFlavorSupported(final DataFlavor f) {
            return f.equals(GRAPH_FLAVOR);
        }

        public Object getTransferData(final DataFlavor f)
            throws UnsupportedFlavorException, IOException {
            if (!isDataFlavorSupported(f)) {
                throw new UnsupportedFlavorException(f);
            }

            return jaxoGraph.copyOf();
        }
    }

    private Clipboard getSystemClipboard() {
        if (fakeSystemClipboard != null) {
            return fakeSystemClipboard;
        }

        try {
            return parentC.getToolkit().getSystemClipboard();
        } catch (SecurityException e) {
            fakeSystemClipboard = new Clipboard("JaxoDraw");
            return fakeSystemClipboard;
        }
    }

    private void systemClipboardUnavailable() {
        parentC.getToolkit().beep();
    }
}
