/** 
 * $id:  $
 */
package org.jvnet.lookout.ui.core.util;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.jvnet.lookout.ui.core.ImageDescriptorProvider;
import org.jvnet.lookout.ui.core.Plugin;

public class Utilities {
	private static ImageRegistry imageRegistry;
	
	private static final ReentrantLock imageLock = new ReentrantLock();
	private static final ReentrantLock imageDescriptorLock = new ReentrantLock();
	
	static {
		imageRegistry = new ImageRegistry();
	}
	
	/**
	 * Returns an image for the image location provided.
	 *  
	 */
	public static Image getImage(String imageLocation, ImageDescriptorProvider provider) {
		
		imageLock.lock();
		
		Image image = imageRegistry.get(imageLocation);
		
		if(image == null) {
			
			ImageDescriptor imageDescriptor = provider.getImageDescriptor(imageLocation);
			
			if(null != imageDescriptor) {
				image = imageDescriptor.createImage();
				
				if(null != image) {
					imageRegistry.put(imageLocation, image);
				}
			}				
		}
		
		imageLock.unlock();        
		
		return image;
	}
	
	/**
	 * Returns the image descriptor for the image location provided.
	 *  
	 */
	public static ImageDescriptor getImageDescriptor(String imageLocation, ImageDescriptorProvider provider) {
		
		imageDescriptorLock.lock();
		
		ImageDescriptor imageDescriptor = imageRegistry.getDescriptor(imageLocation);
		
		if(imageDescriptor == null) {
			
			imageDescriptor = provider.getImageDescriptor(imageLocation);
			
			if(null != imageDescriptor) {
				imageRegistry.put(imageLocation, imageDescriptor);
			}				
		}
		
		imageDescriptorLock.unlock();        
		
		return imageDescriptor;
	}
	
	/**
	 * Internal method. Used to dispose all resources used.
	 */
	public static void cleanup() {
		imageRegistry.dispose();
	}	
	
	public static void showInformationMessage(String message) {
		MessageDialog.openInformation(
				Display.getCurrent().getActiveShell(),
				Plugin.getResourceString("message-info-title"), 
				message);
	}    
	
	public static void showErrorMessage(String message) {        
		MessageDialog.openError(
				Display.getCurrent().getActiveShell(),
				Plugin.getResourceString("message-error-title"), 
				message);
	}    
	
	public static void showWarningMessage(String message) {        
		MessageDialog.openWarning(
				Display.getCurrent().getActiveShell(),                
				Plugin.getResourceString("message-error-title"), 
				message);
	}  
	
	public static void showWarningDialog(String message, IStatus status) {        
		ErrorDialog.openError(
				Display.getCurrent().getActiveShell(),
				Plugin.getResourceString("message-warning-title"), 
				message,
				status,
				IStatus.WARNING);
	}   
	
	public static void showErrorDialog(String message, IStatus status) {        
		ErrorDialog.openError(
				Display.getCurrent().getActiveShell(),
				Plugin.getResourceString("message-error-title"), 
				message,
				status,
				IStatus.ERROR);
	}
	
	public static String showInputDialog(String title, String message, String defaultValue, IInputValidator validator) {
		
		InputDialog dialog = new InputDialog(Display.getCurrent().getActiveShell(),
				title, 
				message,
				defaultValue, 
				validator);

		dialog.open();
		
		return dialog.getValue();
	}
	
	public static Object copy(Object orig) {
        Object obj = null;
        try {
            // Write the object out to a byte array
            FastByteArrayOutputStream fbos = new FastByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(fbos);
            out.writeObject(orig);
            out.flush();
            out.close();

            // Retrieve an input stream from the byte array and read
            // a copy of the object back in. 
            ObjectInputStream in = 
                new ObjectInputStream(fbos.getInputStream());
            obj = in.readObject();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        catch(ClassNotFoundException cnfe) {
            cnfe.printStackTrace();
        }
        return obj;
    }
	
	/**
	 * Copies the specified text into the system clipboard.
	 * 
	 * @param text
	 */
	public static void copyTextToClipboard(String text) {		
        Clipboard clipboard = new Clipboard(Display.getCurrent());
        TextTransfer textTransfer = TextTransfer.getInstance();
        clipboard.setContents(new String[]{text}, new Transfer[]{textTransfer});
        clipboard.dispose();
	}
}
