/*******************************************************************************
 * Copyright (c) 2004, 2007 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
 *******************************************************************************/
package org.eclipse.jface.tests.images;

import junit.framework.Assert;
import junit.framework.TestCase;

import org.eclipse.jface.resource.*;
import org.eclipse.rwt.graphics.Graphics;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * @since 3.1
 */
public class ResourceManagerTest extends TestCase {
    
    private DeviceResourceDescriptor[] descriptors;
    private Image testImage;
    private Image testImage2;
    private Color testColor;
    private Color testColor2;
    private int numDupes;
    
    private DeviceResourceManager globalResourceManager;
    
    private static ImageDescriptor getImage(String path) {
        return AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.rap.ui.tests", path);
    }
    
    private static final class TestDescriptor extends DeviceResourceDescriptor {
        DeviceResourceDescriptor toWrap;
        public static int refCount = 0;
        
        public TestDescriptor(DeviceResourceDescriptor toWrap) {
            this.toWrap = toWrap;
        }
        
        /* (non-Javadoc)
         * @see org.eclipse.jface.resource.DeviceResourceDescriptor#createResource(org.eclipse.swt.graphics.Device)
         */
        public Object createResource(Device device) throws DeviceResourceException {
            Object result = toWrap.createResource(device);
            refCount++;
            return result;
        }
        /* (non-Javadoc)
         * @see org.eclipse.jface.resource.DeviceResourceDescriptor#destroyResource(java.lang.Object)
         */
        public void destroyResource(Object previouslyCreatedObject) {
            refCount--;
            toWrap.destroyResource(previouslyCreatedObject);
        }
        
        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        public boolean equals(Object arg0) {
            if (arg0 instanceof TestDescriptor) {
                TestDescriptor td = (TestDescriptor)arg0;
                
                return td.toWrap.equals(toWrap);
            }
            
            return false;
        }
        
        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        public int hashCode() {
            return toWrap.hashCode();
        }
    }
    
    /* (non-Javadoc)
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception {
        super.setUp();
        TestDescriptor.refCount = 0;
        Display display = Display.getCurrent();
        globalResourceManager = new DeviceResourceManager(display);
        testImage = getImage("icons/anything.gif").createImage(display);
        testImage2 = getImage("icons/binary_co.gif").createImage(display);
//        testColor = new Color(display, new RGB(10, 40, 20));
//        testColor2 = new Color(display, new RGB(230, 100, 26));
        testColor = Graphics.getColor( new RGB(10, 40, 20));
        testColor2 = Graphics.getColor( new RGB(230, 100, 26));
        
        // Array of resource descriptors containing at least one duplicate of each type.
        // If you modify this array, be sure to adjust numDupes as well. Note that some
        // tests index the array directly, so it is a good idea to always add to this
        // array rather than remove from it.
        descriptors = new DeviceResourceDescriptor[] {
                new TestDescriptor(getImage("icons/anything.gif")),
                new TestDescriptor(getImage("icons/anything.gif")),
                new TestDescriptor(getImage("icons/binary_co.gif")),
                new TestDescriptor(getImage("icons/binary_co.gif")),
                new TestDescriptor(getImage("icons/mockeditorpart1.gif")),
                
                new TestDescriptor(getImage("icons/view.gif")), // 5
                new TestDescriptor(ImageDescriptor.createFromImage(testImage2)),
                new TestDescriptor(ImageDescriptor.createFromImage(testImage)),
                new TestDescriptor(ImageDescriptor.createFromImage(testImage)),
                new TestDescriptor(ImageDescriptor.createFromImage(testImage, display)),
                
                new TestDescriptor(ImageDescriptor.createFromImage(testImage, display)),  // 10
                new TestDescriptor(ImageDescriptor.createFromImage(testImage2, display)),
                new TestDescriptor(ColorDescriptor.createFrom(new RGB(10, 200, 54))),
                new TestDescriptor(ColorDescriptor.createFrom(new RGB(10, 200, 54))),
                new TestDescriptor(ColorDescriptor.createFrom(new RGB(200, 220, 54))),
                
                new TestDescriptor(ColorDescriptor.createFrom(testColor)), // 15
                new TestDescriptor(ColorDescriptor.createFrom(testColor)),
                new TestDescriptor(ColorDescriptor.createFrom(testColor2)),
//                new TestDescriptor(ColorDescriptor.createFrom(testColor, display)),
//                new TestDescriptor(ColorDescriptor.createFrom(testColor, display)),
//                new TestDescriptor(ColorDescriptor.createFrom(testColor2, display))
                };
        
        // Let the tests know how many duplicates are in the array
        // RAP [bm]: less duplicates - see above
//        numDupes = 11;
        numDupes = 8;
        // RAPEND: [bm] 

    }
    
    /* (non-Javadoc)
     * @see junit.framework.TestCase#tearDown()
     */
    protected void tearDown() throws Exception {
        super.tearDown();
        globalResourceManager.dispose();
        Assert.assertEquals("Detected leaks", 0, TestDescriptor.refCount);
//        testImage.dispose();
//        testImage2.dispose();
    }
    
    protected void validateResource(Object resource) throws Exception {
        Assert.assertNotNull("Allocated resource was null", resource);
//        if (resource instanceof Image) {
//            Image image = (Image) resource;
//            
//            Assert.assertTrue("Image is disposed", !image.isDisposed());
//            return;
//        }
    }
    
    /**
     * Tests that the descriptors themselves w
     *
     * @throws Exception
     */
    public void testDescriptorAllocations() throws Exception {
        Display display = Display.getCurrent();
        
        // Allocate resources directly using the descriptors.
        Object[] resources = new Object[descriptors.length];
        
        for (int i = 0; i < descriptors.length; i++) {
            DeviceResourceDescriptor next = descriptors[i];
            
            Object resource = next.createResource(display);
            // Ensure that this resource was allocated correctly
            validateResource(resource);
            resources[i] = resource;
        }
        
        // Allocating resources without the manager will not reuse duplicates, so we
        // should get exactly one resource per descriptor.
        
        Assert.assertEquals("Expecting one resource to be allocated per descriptor", 
                descriptors.length, TestDescriptor.refCount);
        
        // Deallocate resources directly using the descriptors
        for (int i = 0; i < descriptors.length; i++) {
            DeviceResourceDescriptor next = descriptors[i];
            
            next.destroyResource(resources[i]);
        }   
    }
    
    public void testDeviceManagerAllocations() throws Exception {
        
        // Allocate resources directly using the descriptors.
        Object[] resources = new Object[descriptors.length];
        
        for (int i = 0; i < descriptors.length; i++) {
            DeviceResourceDescriptor next = descriptors[i];
            
            Object resource = globalResourceManager.create(next);
            // Ensure that this resource was allocated correctly
            validateResource(resource);
            resources[i] = resource;
        }
        
        Assert.assertEquals("Descriptors created from Images should not reallocate Images when the original can be reused",
                testImage, resources[9]);
        
        // Allocating resources without the manager will reuse duplicates, so the number
        // of resources should equal the number of unique descriptors.
        
        Assert.assertEquals("Duplicate descriptors should be reused", 
                descriptors.length - numDupes, 
                TestDescriptor.refCount);
        
        // Deallocate resources directly using the descriptors
        for (int i = 0; i < descriptors.length; i++) {
            DeviceResourceDescriptor next = descriptors[i];
            
            globalResourceManager.destroy(next);
        }
    }
    
    private void allocateResources(ResourceManager mgr, int[] toAllocate) throws Exception {
        for (int i = 0; i < toAllocate.length; i++) {
            int j = toAllocate[i];
            
            validateResource(mgr.create(descriptors[j]));
        }
    }
    
    private void deallocateResources(ResourceManager mgr, int[] toDeallocate) {
        for (int i = 0; i < toDeallocate.length; i++) {
            int j = toDeallocate[i];
            
            mgr.destroy(descriptors[j]);
        }
    }
    
    public void testLocalManagerAllocations() throws Exception {
        // These arrays are indices into the descriptors array. For example, {0,1,7}
        // is a quick shorthand to indicate we should allocate resources 0, 1, and 7.
        int[] gResources = {0, 1, 5, 3, 7, 12, 13, 14};
        int[] lm1Resources = {0, 2, 3, 4, 11, 12, 13, 15};
        int[] lm2Resources = {0, 1, 6, 7, 8, 12, 14, 16};
        
        LocalResourceManager lm1 = new LocalResourceManager(globalResourceManager);
        LocalResourceManager lm2 = new LocalResourceManager(globalResourceManager);
        
        // Allocate a bunch of global resources
        allocateResources(globalResourceManager, gResources);
        
        // Remember how many global resources were allocated
        int initialCount = TestDescriptor.refCount;
        
        // Allocate a bunch of resources in lm1
        allocateResources(lm1, lm1Resources);
        
        // Remember how many global + lm1 resources there are
        int lm1Count = TestDescriptor.refCount;
        
        // Allocate and deallocate a bunch of resources in lm2
        // Ensure that all the lm2 resources were deallocated (we should be
        // back down to the count we had after we allocated lm1 resources)
        allocateResources(lm2, lm2Resources);
        deallocateResources(lm2, lm2Resources);
        Assert.assertEquals(lm1Count, TestDescriptor.refCount);

        // Dispose lm2 (shouldn't do anything since we already deallocated all of its resources)
        // Ensure that this doesn't change any refcounts
        lm2.dispose();
        Assert.assertEquals(lm1Count, TestDescriptor.refCount);
        
        // Dispose lm1 without first deallocating its resources. This should correctly detect
        // what needs to be deallocated from lm1 without affecting any global resources.
        // If everything works, we should be back to the resource count we had after allocating
        // the global resources.
        lm1.dispose();
        Assert.assertEquals(initialCount, TestDescriptor.refCount);
        
    }
    
    /*
     * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=135088
     */
    public void testResourceManagerFind() throws Exception {
    	DeviceResourceDescriptor descriptor = descriptors[0];
    	Object resource = globalResourceManager.find(descriptor);
    	assertNull("Resource should be null since it is not allocated", resource);
    	resource = globalResourceManager.create(descriptor);
    	
        // Ensure that the resource was allocated correctly
        validateResource(resource);
        
        // Now the resource should be found
        Object foundResource = globalResourceManager.find(descriptor);
    	assertNotNull("Found resource should not be null", foundResource);
    	assertTrue("Found resource should be an image", foundResource instanceof Image);
    	
    	// Destroy the resource we created
    	globalResourceManager.destroy(descriptor);
    }
}
