/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Steven Ketcham (sketcham@dsicdi.com) - Bug 42451
 *     [Dialogs] ImageRegistry throws null pointer exception in
 *     application with multiple Display's
 *******************************************************************************/
package org.eclipse.jface.resource;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.util.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Display;

/**
 * An image registry maintains a mapping between symbolic image names 
 * and SWT image objects or special image descriptor objects which
 * defer the creation of SWT image objects until they are needed.
 * <p>
 * An image registry owns all of the image objects registered
 * with it, and automatically disposes of them when the SWT Display
 * that creates the images is disposed. Because of this, clients do not 
 * need to (indeed, must not attempt to) dispose of these images themselves.
 * </p>
 * <p>
 * Clients may instantiate this class (it was not designed to be subclassed).
 * </p>
 * <p>
 * Unlike the FontRegistry, it is an error to replace images. As a result
 * there are no events that fire when values are changed in the registry
 * </p>
 */
public class ImageRegistry {
    /**
     * display used when getting images
     */
    private Display display;

    private ResourceManager manager;

    private Map table;
    
    private Runnable disposeRunnable = new Runnable() {
        public void run() {
            dispose();
        }
    };
    
    /**
     * Contains the data for an entry in the registry. 
     */
    private static class Entry {
        protected Image image;

        protected ImageDescriptor descriptor;
    }
    
    private static class OriginalImageDescriptor extends ImageDescriptor {
        private Image original;
        private int refCount = 0;
        private Device originalDisplay;
        
        public OriginalImageDescriptor(Image original, Device originalDisplay) {
            this.original = original;
            this.originalDisplay = originalDisplay;
        }
        
        public Object createResource(Device device) throws DeviceResourceException {
            if (device == originalDisplay) {
                refCount++;
                return original;
            }
            return super.createResource(device);
        }
        
        public void destroyResource(Object toDispose) {
            if (original == toDispose) {
                refCount--;
                if (refCount == 0) {
                    original.dispose();
                    original = null;
                }
            } else {
                super.destroyResource(toDispose);
            }
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.resource.ImageDescriptor#getImageData()
         */
        public ImageData getImageData() {
            return original.getImageData();
        }
    }
        
    /**
     * Creates an empty image registry.
     * <p>
     * There must be an SWT Display created in the current 
     * thread before calling this method.
     * </p>
     */
    public ImageRegistry() {
        this(Display.getCurrent());
    }

    /**
     * Creates an empty image registry using the given resource manager to allocate images.
     * 
     * @param manager the resource manager used to allocate images
     * 
     * @since 3.1
     */
    public ImageRegistry(ResourceManager manager) {
        Assert.isNotNull(manager);
        Device dev = manager.getDevice();
        if (dev instanceof Display) {
            this.display = (Display)dev;
        }
        this.manager = manager;
        manager.disposeExec(disposeRunnable);
    }
    
    /**
     * Creates an empty image registry.
     * 
     * @param display this <code>Display</code> must not be 
     *        <code>null</code> and must not be disposed in order
     *        to use this registry
     */
    public ImageRegistry(Display display) {
        this(JFaceResources.getResources(display));
    }
    
    /**
     * Returns the image associated with the given key in this registry, 
     * or <code>null</code> if none.
     * 
     * @param key the key
     * @return the image, or <code>null</code> if none
     */
    public Image get(String key) {

        // can be null
        if (key == null) {
            return null;
        }
        
        if (display != null) {
            /**
             * NOTE, for backwards compatibility the following images are supported
             * here, they should never be disposed, hence we explicitly return them 
             * rather then registering images that SWT will dispose.  
             * 
             * Applications should go direclty to SWT for these icons.
             * 
             * @see Display.getSystemIcon(int ID)
             */
            int swtKey = -1;
            if (key.equals(Dialog.DLG_IMG_INFO)) {
                swtKey = SWT.ICON_INFORMATION;
            }
            if (key.equals(Dialog.DLG_IMG_QUESTION)) {
                swtKey = SWT.ICON_QUESTION;
            }
            if (key.equals(Dialog.DLG_IMG_WARNING)) {
                swtKey = SWT.ICON_WARNING;
            }
            if (key.equals(Dialog.DLG_IMG_ERROR)) {
                swtKey = SWT.ICON_ERROR;
            }
            // if we actually just want to return an SWT image do so without
            // looking in the registry
            if (swtKey != -1) {
                final Image[] image = new Image[1];
                final int id = swtKey;
                display.syncExec(new Runnable() {
                    public void run() {
                        image[0] = display.getSystemImage(id);
                    }
                });
                return image[0];
            }
        }

        Entry entry = getEntry(key);
        if (entry == null) {
            return null;
        }
        
        if (entry.image == null) {
            entry.image = manager.createImageWithDefault(entry.descriptor);
        }
        
        return entry.image;
    }

    /**
     * Returns the descriptor associated with the given key in this registry, 
     * or <code>null</code> if none.
     *
     * @param key the key
     * @return the descriptor, or <code>null</code> if none
     * @since 2.1
     */
    public ImageDescriptor getDescriptor(String key) {
        Entry entry = getEntry(key);
        if (entry == null) {
            return null;
        }
        
        return entry.descriptor;
    }

    /**
     * Adds (or replaces) an image descriptor to this registry. The first time
     * this new entry is retrieved, the image descriptor's image will be computed 
     * (via </code>ImageDescriptor.createImage</code>) and remembered. 
     * This method replaces an existing image descriptor associated with the 
     * given key, but fails if there is a real image associated with it.
     *
     * @param key the key
     * @param descriptor the ImageDescriptor
     * @exception IllegalArgumentException if the key already exists
     */
    public void put(String key, ImageDescriptor descriptor) {
        Entry entry = getEntry(key);
        if (entry == null) {
            entry = new Entry();
            getTable().put(key, entry);
        }
        
        if (entry.image != null) {
            throw new IllegalArgumentException(
                    "ImageRegistry key already in use: " + key); //$NON-NLS-1$            
        }
        
        entry.descriptor = descriptor;
    }

    /**
     * Adds an image to this registry.  This method fails if there
     * is already an image or descriptor for the given key.
     * <p>
     * Note that an image registry owns all of the image objects registered
     * with it, and automatically disposes of them when the SWT Display is disposed. 
     * Because of this, clients must not register an image object
     * that is managed by another object.
     * </p>
     *
     * @param key the key
     * @param image the image
     * @exception IllegalArgumentException if the key already exists
     */
    public void put(String key, Image image) {
        Entry entry = getEntry(key);
        
        if (entry == null) {
            entry = new Entry();
            putEntry(key, entry);
        }
        
        if (entry.image != null || entry.descriptor != null) {
            throw new IllegalArgumentException(
                    "ImageRegistry key already in use: " + key); //$NON-NLS-1$            
        }
        
        entry.image = image;
        entry.descriptor = new OriginalImageDescriptor(image, manager.getDevice());
        
        try {
            manager.create(entry.descriptor);
        } catch (DeviceResourceException e) {            
        }
    }

    /**
     * Removes an image from this registry.  
     * If an SWT image was allocated, it is disposed.
     * This method has no effect if there is no image or descriptor for the given key.
     * @param key the key
     */
    public void remove(String key) {
        ImageDescriptor descriptor = getDescriptor(key);
        if (descriptor != null) {
            manager.destroy(descriptor);
            getTable().remove(key);
        }
    }

    private Entry getEntry(String key) {
        return (Entry) getTable().get(key);
    }

    private void putEntry(String key, Entry entry) {
        getTable().put(key, entry);
    }

    private Map getTable() {
        if (table == null) {
            table = new HashMap(10);
        }
        return table;
    }
    
    /**
     * Disposes this image registry, disposing any images
     * that were allocated for it, and clearing its entries.
     * 
     * @since 3.1
     */
    public void dispose() {
        manager.cancelDisposeExec(disposeRunnable);
        
        if (table != null) {
            for (Iterator i = table.values().iterator(); i.hasNext();) {
                Entry entry = (Entry) i.next();
                if (entry.image != null) {
                    manager.destroyImage(entry.descriptor);
                }
            }
            table = null;
        }
        display = null;
    }
}
