/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.resources.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
import com.google.gwt.resources.client.impl.ImageResourcePrototype;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Tests ImageResource generation.
 */
public class ImageResourceTest extends GWTTestCase {
  interface ExternalResources extends ClientBundle {
    @ImageOptions(preventInlining = true)
    @Source("16x16.png")
    ImageResource i16x16();

    @ImageOptions(preventInlining = true)
    @Source("32x32.png")
    ImageResource i32x32();

    @ImageOptions(repeatStyle = RepeatStyle.Both)
    @Source("16x16.png")
    ImageResource i16x16RepeatBoth();

    @ImageOptions(repeatStyle = RepeatStyle.Both)
    @Source("32x32.png")
    ImageResource i32x32RepeatBoth();
  }

  interface Resources extends ClientBundle {
    @Source("animated.gif")
    ImageResource animated();

    /**
     * This image shouldn't be re-encoded as a PNG or it will dramatically
     * increase in size, although it's still small enough to be encoded as a
     * data URL as-is.
     */
    ImageResource complexLossy();

    @Source("16x16.png")
    ImageResource i16x16();

    @Source("16x16.png")
    @ImageOptions(repeatStyle = RepeatStyle.Horizontal)
    ImageResource i16x16Horizontal();

    @Source("16x16.png")
    @ImageOptions(repeatStyle = RepeatStyle.Vertical)
    ImageResource i16x16Vertical();

    @Source("32x32.png")
    ImageResource i32x32();

    @Source("32x32.png")
    @ImageOptions(repeatStyle = RepeatStyle.Horizontal)
    ImageResource i32x32Horizontal();

    @Source("32x32.png")
    @ImageOptions(repeatStyle = RepeatStyle.Vertical)
    ImageResource i32x32Vertical();

    @Source("64x64.png")
    ImageResource i64x64();

    @Source("64x64.png")
    ImageResource i64x64Dup();

    @Source("64x64-dup.png")
    ImageResource i64x64Dup2();

    // Test default filename lookup while we're at it
    ImageResource largeLossless();

    // Test default filename lookup while we're at it
    ImageResource largeLossy();
  
    @Source("64x64.png")
    @ImageOptions(width = 32)
    ImageResource scaledDown();
    
    @Source("64x64.png")
    @ImageOptions(width = 128)
    ImageResource scaledUp();
  }

  @Override
  public String getModuleName() {
    return "com.google.gwt.resources.Resources";
  }

  public void testAnimated() {
    Resources r = GWT.create(Resources.class);

    ImageResource a = r.animated();

    assertTrue(a.isAnimated());
    assertFalse(((ImageResourcePrototype) a).isLossy());
    assertEquals(16, a.getWidth());
    assertEquals(16, a.getHeight());
    assertEquals(0, a.getLeft());
    assertEquals(0, a.getTop());

    // Make sure the animated image is encoded separately
    assertFalse(a.getSafeUri().equals(r.i16x16().getSafeUri()));
  }

  public void testDedup() {
    Resources r = GWT.create(Resources.class);

    ImageResource a = r.i64x64();
    ImageResource b = r.i64x64Dup();
    ImageResource c = r.i64x64Dup2();
    assertEquals(64, a.getHeight());
    assertEquals(64, a.getWidth());

    assertEquals(a.getLeft(), b.getLeft());
    assertEquals(a.getLeft(), c.getLeft());

    assertEquals(a.getTop(), b.getTop());
    assertEquals(a.getTop(), c.getTop());

    delayTestFinish(10000);
    // See if the size of the image strip is what we expect
    Image i = new Image(a.getSafeUri());
    i.addLoadHandler(new LoadHandler() {
      @Override
      public void onLoad(LoadEvent event) {
        finishTest();
      }
    });
    i.addErrorHandler(new ErrorHandler() {
      @Override
      public void onError(ErrorEvent event) {
        fail("ErrorEvent");
      }
    });

    RootPanel.get().add(i);
  }

  public void testPacking() {
    Resources r = GWT.create(Resources.class);

    ImageResource i64 = r.i64x64();
    ImageResource lossy = r.largeLossy();
    ImageResource lossless = r.largeLossless();

    assertFalse(((ImageResourcePrototype) lossless).isLossy());

    // Make sure that the large, lossy image isn't bundled with the rest
    assertTrue(((ImageResourcePrototype) lossy).isLossy());
    assertTrue(!i64.getSafeUri().equals(lossy.getSafeUri()));
    assertFalse(lossy instanceof ImageResourcePrototype.Bundle);

    assertEquals(16, r.i16x16Vertical().getWidth());
    assertEquals(16, r.i16x16Vertical().getHeight());

    assertEquals(16, r.i16x16Horizontal().getWidth());
    assertEquals(16, r.i16x16Horizontal().getHeight());

    // Check scaling and aspect ratio
    assertEquals(32, r.scaledDown().getWidth());
    assertEquals(32, r.scaledDown().getHeight());
    assertEquals(128, r.scaledUp().getWidth());
    assertEquals(128, r.scaledUp().getHeight());
  }

  public void testPreventInlining() {
    ExternalResources r = GWT.create(ExternalResources.class);
    ImageResource a = r.i16x16();
    ImageResource b = r.i32x32();

    // Should never be a data URL
    assertFalse(a.getURL().startsWith("data:"));
    assertFalse(b.getURL().startsWith("data:"));
    // Should be fetched from different URLs
    assertFalse(a.getURL().equals(b.getURL()));

    // No image packing
    assertEquals(0, a.getTop());
    assertEquals(0, a.getLeft());
    assertFalse(a instanceof ImageResourcePrototype.Bundle);
    assertEquals(0, b.getTop());
    assertEquals(0, b.getLeft());
    assertFalse(b instanceof ImageResourcePrototype.Bundle);
  }

  /**
   * Tests that RepeatStyle.Both creates standalone images.
   */
  public void testRepeatStyleBoth() {
    ExternalResources r = GWT.create(ExternalResources.class);
    ImageResource a = r.i16x16RepeatBoth();
    ImageResource b = r.i32x32RepeatBoth();

    // Should be fetched from different URLs
    assertFalse(a.getURL().equals(b.getURL()));

    // No image packing
    assertEquals(0, a.getTop());
    assertEquals(0, a.getLeft());
    assertFalse(a instanceof ImageResourcePrototype.Bundle);
    assertEquals(0, b.getTop());
    assertEquals(0, b.getLeft());
    assertFalse(b instanceof ImageResourcePrototype.Bundle);
  }

  @SuppressWarnings("deprecation")
  public void testSafeUri() {
    Resources r = GWT.create(Resources.class);

    assertEquals(r.i64x64().getSafeUri().asString(), r.i64x64().getURL());
  }
}
