/**
 * This program and the accompanying materials
 * are made available under the terms of the License
 * which accompanies this distribution in the file LICENSE.txt
 */
package com.archimatetool.editor.ui;

import org.eclipse.core.commands.common.EventManager;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.dnd.ByteArrayTransfer;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;

/**
 * Clipboard wrapper for application copy and paste
 * This is based on org.eclipse.gef.ui.actions.Clipboard and org.eclipse.gef.dnd.SimpleObjectTransfer
 * 
 * @author Phillip Beauvoir
 */
public class LocalClipboard extends EventManager {

    private static LocalClipboard defaultClipboard = new LocalClipboard();
    
    private static final ByteArrayTransfer TRANSFER = new ByteArrayTransfer() {
        private final String TYPE_NAME = "com.archimatetool.editor.clipboard.transfer"; //$NON-NLS-1$
        private final int TYPE_ID = registerType(TYPE_NAME);

        private Object object;

        @Override
        protected int[] getTypeIds() {
            return new int[] { TYPE_ID };
        }

        @Override
        protected String[] getTypeNames() {
            return new String[] { TYPE_NAME };
        }
        
        @Override
        public void javaToNative(Object object, TransferData transferData) {
            this.object = object;
            super.javaToNative(TYPE_NAME.getBytes(), transferData);
        }

        @Override
        public Object nativeToJava(TransferData transferData) {
            Object result = super.nativeToJava(transferData);
            if(!(result instanceof byte[]) && !TYPE_NAME.equals(new String((byte[])result))) {
                return null;
            }
            
            return object;
        }
    };
    
    /**
     * @return the default clipboard
     */
    public static LocalClipboard getDefault() {
        return defaultClipboard;
    }
    
    private Clipboard clipBoard = new Clipboard(null);
    
    private LocalClipboard() {
        if(PlatformUI.isWorkbenchRunning()) {
            // The System clipboard contents may have changed and some clients may wish to check it.
            PlatformUI.getWorkbench().addWindowListener(new IWindowListener() {
                @Override
                public final void windowActivated(IWorkbenchWindow window) {
                    fireClipboardChanged(getContents());
                }

                @Override
                public final void windowClosed(IWorkbenchWindow window) {
                }

                @Override
                public final void windowDeactivated(IWorkbenchWindow window) {
                }

                @Override
                public final void windowOpened(IWorkbenchWindow window) {
                }
            });
        }
    }
    
    /**
     * @return contents of the clipboard
     */
    public Object getContents() {
        return clipBoard.getContents(TRANSFER);
    }

    /**
     * Sets the contents of the clipboard. This will erase the previous contents
     * of this as well as the system clipboard. The provided contents will not
     * be garbage-collected until some other contents are set using this method.
     * 
     * @param contents the new contents
     */
    public void setContents(Object contents) {
        clipBoard.setContents(new Object[] { contents }, new Transfer[] { TRANSFER });
        fireClipboardChanged(contents);
    }
    
    /**
     * Add a ClipboardListener
     * @param l
     */
    public void addListener(ILocalClipboardListener l) {
        addListenerObject(l);
    }

    /**
     * Remove a ClipboardListener
     * @param l
     */
    public void removeListener(ILocalClipboardListener l) {
        removeListenerObject(l);
    }

    private void fireClipboardChanged(Object contents) {
        for(Object element : getListeners()) {
            final ILocalClipboardListener l = (ILocalClipboardListener)element;
            SafeRunner.run(new SafeRunnable() {
                @Override
                public void run() {
                    l.clipBoardChanged(contents);
                }
            });
        }
    }
}

@@ -1112,16 +1112,45 @@
 ransfer%22
+ + System.currentTimeMillis()
 ; //$NON
@@ -1795,23 +1795,31 @@
     
-Object result =
+byte bytes%5B%5D = (byte%5B%5D)
  sup
@@ -1841,32 +1841,33 @@
 (transferData);%0A
+%0A
             if(!
@@ -1869,40 +1869,74 @@
  if(
-!(result instanceof byte%5B%5D) && !
+bytes != null) %7B%0A                try %7B%0A                    return 
 TYPE
@@ -1963,56 +1963,247 @@
 ing(
-(
 byte
-%5B%5D)result))) %7B%0A                return null;
+s)) ? object : null;%0A                %7D%0A                catch(Exception ex) %7B%0A                    // Something weird on Linux throwing NPE...%0A                    // See https://github.com/archimatetool/archi/issues/592%0A                %7D
 %0A   
@@ -2245,22 +2245,20 @@
  return 
-object
+null
 ;%0A      

Fix for Linux Clipboard issue