/*
 * 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.rg;

import com.google.gwt.core.ext.BadPropertyValueException;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.dev.util.StringKey;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.collect.Maps;
import com.google.gwt.dev.util.collect.Sets;
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.resources.ext.AbstractResourceGenerator;
import com.google.gwt.resources.ext.ClientBundleFields;
import com.google.gwt.resources.ext.ClientBundleRequirements;
import com.google.gwt.resources.ext.ResourceContext;
import com.google.gwt.resources.ext.ResourceGeneratorUtil;
import com.google.gwt.resources.ext.SupportsGeneratorResultCaching;
import com.google.gwt.resources.rg.ImageBundleBuilder.Arranger;
import com.google.gwt.resources.rg.ImageBundleBuilder.ImageRect;
import com.google.gwt.safehtml.shared.UriUtils;
import com.google.gwt.user.rebind.SourceWriter;
import com.google.gwt.user.rebind.StringSourceWriter;
import com.google.gwt.util.tools.Utility;

import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

/**
 * Builds an image strip for all ImageResources defined within an ClientBundle.
 */
public final class ImageResourceGenerator extends AbstractResourceGenerator
    implements SupportsGeneratorResultCaching {
  /**
   * Represents a file that contains multiple image regions.
   */
  static class BundledImage extends DisplayedImage {
    private static final String MIME_TYPE_IMAGE_PNG = "image/png";
    private final ImageBundleBuilder builder;
    private boolean dirty = false;
    private Map<LocalizedImage, ImageRect> images;
    private Set<LocalizedImage> rtlImages = Sets.create();
    private Map<ImageResourceDeclaration, LocalizedImage> localizedByImageResource;
    private String normalContentsUrlExpression;
    private String rtlContentsUrlExpression;

    public BundledImage() {
      builder = new ImageBundleBuilder();
      images = Maps.create();
      localizedByImageResource = Maps.create();
    }

    @Override
    public Class<?> getResourceType() {
      return ImageResourcePrototype.Bundle.class;
    }

    public LocalizedImage addImage(TreeLogger logger, ResourceContext context,
        ImageResourceDeclaration image) throws UnableToCompleteException,
        CannotBundleImageException {

      LocalizedImage localized = LocalizedImage.create(logger, context, image);
      localizedByImageResource = Maps.put(localizedByImageResource, image, localized);
      if (images.containsKey(localized)) {
        return localized;
      }

      dirty = true;
      ImageRect rect = null;
      try {
        rect = builder.assimilate(logger, image.get(), localized.getUrl());
        if (context.supportsDataUrls()) {
          // Treat the image as though it were external
          builder.removeMapping(image.get());
          throw new CannotBundleImageException(localized, rect);
        }
        images = Maps.put(images, localized, rect);
      } catch (UnsuitableForStripException e) {
        rect = e.getImageRect();
        throw new CannotBundleImageException(localized, rect);
      } finally {
        if (rect != null) {
          rect.setHeight(image.getScaleHeight());
          rect.setWidth(image.getScaleWidth());
        }
      }
      assert rect != null : "No ImageRect";
      return localized;
    }

    public ImageBundleBuilder getImageBundleBuilder() {
      return builder;
    }

    @Override
    public ImageRect getImageRect(ImageResourceDeclaration image) {
      return images.get(localizedByImageResource.get(image));
    }

    @Override
    public void render(TreeLogger logger, ResourceContext context,
        ClientBundleFields fields, RepeatStyle repeatStyle)
        throws UnableToCompleteException {
      if (builder.getImageCount() == 0) {
        // No data
        return;
      }

      if (dirty) {
        Arranger arranger;
        switch (repeatStyle) {
          case None:
            arranger = new ImageBundleBuilder.BestFitArranger();
            break;
          case Horizontal:
            arranger = new ImageBundleBuilder.VerticalArranger();
            break;
          case Vertical:
            arranger = new ImageBundleBuilder.HorizontalArranger();
            break;
          case Both:
            arranger = new ImageBundleBuilder.IdentityArranger();
            break;
          default:
            logger.log(TreeLogger.ERROR, "Unknown RepeatStyle " + repeatStyle);
            throw new UnableToCompleteException();
        }
        URL normalContents = renderToTempPngFile(logger, builder, arranger);
        normalContentsUrlExpression = context.deploy(normalContents, MIME_TYPE_IMAGE_PNG, false);

        if (!rtlImages.isEmpty()) {
          for (LocalizedImage rtlImage : rtlImages) {
            // Create a transformation to mirror about the Y-axis and translate
            AffineTransform tx = new AffineTransform();
            ImageRect imageRect = images.get(rtlImage);
            tx.setTransform(-1, 0, 0, 1, imageRect.getWidth(), 0);
            imageRect.setTransform(tx);
          }
          URL rtlContents =
              renderToTempPngFile(logger, builder, new ImageBundleBuilder.IdentityArranger());
          assert rtlContents != null;
          rtlContentsUrlExpression = context.deploy(rtlContents, MIME_TYPE_IMAGE_PNG, false);
        }

        dirty = false;
        if (logger.isLoggable(TreeLogger.DEBUG)) {
          logger.log(TreeLogger.DEBUG, "Composited " + builder.getImageCount() + " images");
        }
      }

      JClassType stringType =
          context.getGeneratorContext().getTypeOracle().findType(String.class.getCanonicalName());

      // Create the field that holds the normal contents
      assert normalContentsUrlExpression != null;
      normalContentsFieldName = fields.define(stringType, "bundledImage_"
          + repeatStyle.name(), normalContentsUrlExpression, true, true);

      // Optionally create the field that holds the RTL contents
      if (rtlContentsUrlExpression != null) {
        rtlContentsFieldName = fields.define(stringType, "bundledImage_"
            + repeatStyle.name() + "_rtl", rtlContentsUrlExpression, true, true);
      }
    }

    @Override
    public void setRtlImage(LocalizedImage image) {
      rtlImages = Sets.add(rtlImages, image);
    }
  }

  /**
   * This key is used to determine which DisplayedImage a given set of image
   * bytes should be associated with.
   */
  static class BundleKey extends StringKey {
    private static String key(ImageResourceDeclaration image, boolean isExternal) {
      if (isExternal) {
        return "External: " + image.get();
      }
      // test mirrored in prepare(), make sure to keep them in sync
      if (image.isPreventInlining() || image.getRepeatStyle() == RepeatStyle.Both) {
        return "Unbundled: " + image.get();
      }
      return "Arranged: " + image.getRepeatStyle().toString();
    }

    private final RepeatStyle repeatStyle;

    public BundleKey(ImageResourceDeclaration image, boolean isExternal) {
      super(key(image, isExternal));
      this.repeatStyle = image.getRepeatStyle();
    }

    public RepeatStyle getRepeatStyle() {
      return repeatStyle;
    }

    public boolean isExternal() {
      return get().startsWith("External: ");
    }
  }

  /**
   * This is shared that can be shared across permutations for a given
   * ClientBundle .
   */
  static class CachedState {
    public final Map<BundleKey, BundledImage> bundledImages =
        new LinkedHashMap<BundleKey, BundledImage>();
    public final Map<BundleKey, ExternalImage> externalImages =
        new LinkedHashMap<BundleKey, ExternalImage>();
  }

  /**
   * Associates an ImageRect and a LocalizedImage.
   */
  static class CannotBundleImageException extends Exception {
    private final ImageRect imageRect;
    private final LocalizedImage localized;

    public CannotBundleImageException(LocalizedImage localized, ImageRect imageRect) {
      this.localized = localized;
      this.imageRect = imageRect;
    }

    public ImageRect getImageRect() {
      return imageRect;
    }

    public LocalizedImage getLocalizedImage() {
      return localized;
    }
  }

  /**
   * Represents a file that contains image data.
   */
  abstract static class DisplayedImage {
    protected String normalContentsFieldName;
    protected String rtlContentsFieldName;

    public abstract Class<?> getResourceType();

    public abstract ImageRect getImageRect(ImageResourceDeclaration image);

    /**
     * Only valid after calling {@link #render}.
     */
    public String getNormalContentsFieldName() {
      return normalContentsFieldName;
    }

    /**
     * Only valid after calling {@link #render}, may be <code>null</code> if
     * there is no RTL version of the image.
     */
    public String getRtlContentsFieldName() {
      return rtlContentsFieldName;
    }

    public abstract void setRtlImage(LocalizedImage image);

    abstract void render(TreeLogger logger, ResourceContext context,
        ClientBundleFields fields, RepeatStyle repeatStyle)
        throws UnableToCompleteException;
  }

  /**
   * Represents a file that contains exactly one image.
   */
  static class ExternalImage extends DisplayedImage {
    private final ImageResourceDeclaration image;
    private boolean isRtl;
    private final LocalizedImage localized;
    private final ImageRect rect;

    /**
     * Create an unbundled image.
     */
    public ExternalImage(ImageResourceDeclaration image, LocalizedImage localized, ImageRect rect) {
      this.image = image;
      this.localized = localized;
      this.rect = rect;
    }

    @Override
    public Class<?> getResourceType() {
      return ImageResourcePrototype.class;
    }

    @Override
    public ImageRect getImageRect(ImageResourceDeclaration image) {
      return this.image.equals(image) ? rect : null;
    }

    @Override
    public void render(TreeLogger logger, ResourceContext context,
        ClientBundleFields fields, RepeatStyle repeatStyle)
        throws UnableToCompleteException {
      JClassType stringType =
          context.getGeneratorContext().getTypeOracle().findType(String.class.getCanonicalName());

      String contentsExpression = context.deploy(
          localized.getUrl(), null, image.isPreventInlining());
      normalContentsFieldName = fields.define(stringType, "externalImage",
          contentsExpression, true, true);

      if (isRtl) {
        // Create a transformation to mirror about the Y-axis and translate
        AffineTransform tx = new AffineTransform();
        tx.setTransform(-1, 0, 0, 1, rect.getWidth(), 0);
        rect.setTransform(tx);

        byte[] rtlData = ImageBundleBuilder.toPng(logger, rect);
        String rtlContentsUrlExpression = context.deploy(image.getName()
            + "_rtl.png", "image/png", rtlData, image.isPreventInlining());
        rtlContentsFieldName = fields.define(stringType, "externalImage_rtl",
            rtlContentsUrlExpression, true, true);
      }
    }

    @Override
    public void setRtlImage(LocalizedImage localized) {
      if (this.localized.equals(localized)) {
        isRtl = true;
      }
    }
  }

  /**
   * This represent how the user described the image in the original Java
   * source. Its identity is based on the ImageResource JMethod.
   */
  static class ImageResourceDeclaration extends StringKey {
    private static String key(JMethod method) {
      return method.getEnclosingType().getQualifiedSourceName() + "." + method.getName();
    }

    private final String name;
    private final JMethod method;
    private final ImageOptions options;

    public ImageResourceDeclaration(JMethod method) {
      super(key(method));
      this.name = method.getName();
      this.method = method;
      this.options = method.getAnnotation(ImageOptions.class);
    }

    public JMethod getMethod() {
      return method;
    }

    public String getName() {
      return name;
    }

    public RepeatStyle getRepeatStyle() {
      return options == null ? RepeatStyle.None : options.repeatStyle();
    }

    public int getScaleHeight() {
      return options == null ? -1 : options.height();
    }

    public int getScaleWidth() {
      return options == null ? -1 : options.width();
    }

    public boolean isFlipRtl() {
      return options == null ? false : options.flipRtl();
    }
    
    public boolean isPreventInlining() {
      return options == null ? false : options.preventInlining();
    }
  }

  /**
   * This represents the particular collections of bits associated with a
   * localized resource that a permutation will use. Its identity is based on
   * the content hash of the resolved data and any transformations that will be
   * applied to the data.
   */
  static class LocalizedImage extends StringKey {
    public static LocalizedImage create(TreeLogger logger,
        ResourceContext context, ImageResourceDeclaration image)
        throws UnableToCompleteException {

      URL[] resources = ResourceGeneratorUtil.findResources(logger, context, image.getMethod());

      if (resources.length != 1) {
        logger.log(TreeLogger.ERROR, "Exactly one image may be specified", null);
        throw new UnableToCompleteException();
      }

      URL resource = resources[0];

      LocalizedImage toReturn = new LocalizedImage(image, resource);
      return toReturn;
    }

    private static String key(ImageResourceDeclaration image, URL url) {
      return Util.computeStrongName(Util.readURLAsBytes(url)) + ":"
          + image.getScaleHeight() + ":" + image.getScaleWidth();
    }

    private final ImageResourceDeclaration image;
    private final URL url;

    public LocalizedImage(LocalizedImage other, URL alternateUrl) {
      this(other.image, alternateUrl);
    }

    private LocalizedImage(ImageResourceDeclaration image, URL url) {
      super(key(image, url));
      this.image = image;
      this.url = url;
    }

    public URL getUrl() {
      return url;
    }
  }

  /**
   * Re-encode an image as a PNG to strip random header data.
   */
  private static URL renderToTempPngFile(TreeLogger logger,
      ImageBundleBuilder builder, Arranger arranger)
      throws UnableToCompleteException {
    try {
      byte[] imageBytes = builder.render(logger, arranger);
      if (imageBytes == null) {
        return null;
      }

      File file = File.createTempFile(ImageResourceGenerator.class.getSimpleName(), ".png");
      file.deleteOnExit();
      Util.writeBytesToFile(logger, file, imageBytes);
      return file.toURI().toURL();
    } catch (IOException ex) {
      logger.log(TreeLogger.ERROR, "Unable to write re-encoded PNG", ex);
      throw new UnableToCompleteException();
    }
  }

  /**
   * This is used to short-circuit the {@link #prepare} method.
   */
  private boolean prepared;
  private CachedState shared;

  @Override
  public String createAssignment(TreeLogger logger, ResourceContext context, JMethod method)
      throws UnableToCompleteException {
    String name = method.getName();

    ImageResourceDeclaration image = new ImageResourceDeclaration(method);
    DisplayedImage bundle = getImage(image);

    SourceWriter sw = new StringSourceWriter();
    sw.println("new " + bundle.getResourceType().getCanonicalName() + "(");
    sw.indent();
    sw.println('"' + name + "\",");

    ImageRect rect = bundle.getImageRect(image);
    if (rect == null) {
      throw new NullPointerException("No ImageRect ever computed for " + name);
    }

    String[] urlExpressions =
        new String[] {bundle.getNormalContentsFieldName(), bundle.getRtlContentsFieldName()};
    assert urlExpressions[0] != null : "No primary URL expression for " + name;

    if (urlExpressions[1] == null) {
      sw.println(UriUtils.class.getName() + ".fromTrustedString(" + urlExpressions[0] + "),");
    } else {
      sw.println(UriUtils.class.getName() + ".fromTrustedString("
          + "com.google.gwt.i18n.client.LocaleInfo.getCurrentLocale().isRTL() ?"
          + urlExpressions[1] + " : " + urlExpressions[0] + "),");
    }
    sw.println(rect.getLeft() + ", " + rect.getTop() + ", " + rect.getWidth() + ", "
        + rect.getHeight() + ", " + rect.isAnimated() + ", " + rect.isLossy());

    sw.outdent();
    sw.print(")");

    return sw.toString();
  }

  /**
   * We use this as a signal that we have received all image methods and can now
   * create the bundled images.
   */
  @Override
  public void createFields(TreeLogger logger, ResourceContext context, ClientBundleFields fields)
      throws UnableToCompleteException {
    renderImageMap(logger, context, fields, shared.bundledImages);
    renderImageMap(logger, context, fields, shared.externalImages);
  }

  @Override
  public void init(TreeLogger logger, ResourceContext context) {
    String key = createCacheKey(context);
    shared = context.getCachedData(key, CachedState.class);
    prepared = shared != null;
    if (prepared) {
      logger.log(TreeLogger.DEBUG, "Using cached data");
    } else {
      shared = new CachedState();
      context.putCachedData(key, shared);
    }
  }

  /**
   * Process each image method. This will either assign the image to an
   * ImageBundleBuilder or reencode an external image.
   */
  @Override
  public void prepare(TreeLogger logger, ResourceContext context,
      ClientBundleRequirements requirements, JMethod method)
      throws UnableToCompleteException {
    if (prepared) {
      logger.log(TreeLogger.DEBUG, "ImageResources already prepared");
      return;
    }

    ImageResourceDeclaration image = new ImageResourceDeclaration(method);

    boolean cannotBundle = false;
    DisplayedImage displayed = null;
    LocalizedImage localizedImage;
    ImageRect rect;
    try {
      BundledImage bundledImage = (BundledImage) getImage(image);
      localizedImage = bundledImage.addImage(logger, context, image);
      rect = bundledImage.getImageRect(image);
      displayed = bundledImage;
      // mirrors the "unbundled" case in BundleKey.
      if (image.isPreventInlining() || image.getRepeatStyle() == RepeatStyle.Both) {
        cannotBundle = true;
      }
    } catch (CannotBundleImageException e) {
      cannotBundle = true;
      localizedImage = e.getLocalizedImage();
      rect = e.getImageRect();
    }

    // Store the image externally
    if (cannotBundle) {
      if (rect.isAnimated() || rect.isLossy()) {
        // Don't re-encode
      } else {
        /*
         * Try to re-compress the image, but only use the re-compressed bytes if
         * they actually offer a space-savings.
         */
        try {
          int originalSize = getContentLength(localizedImage.getUrl());

          // Re-encode the data
          URL reencodedContents = reencodeToTempFile(logger, rect);
          int newSize = getContentLength(reencodedContents);

          // But only use it if we did a better job on compression
          if (newSize < originalSize) {
            if (logger.isLoggable(TreeLogger.SPAM)) {
              logger.log(TreeLogger.SPAM, "Reencoded image and saved "
                  + (originalSize - newSize) + " bytes");
            }
            localizedImage = new LocalizedImage(localizedImage, reencodedContents);
          }
        } catch (IOException e2) {
          // Non-fatal, but weird
          logger.log(TreeLogger.WARN,
              "Unable to determine before/after size when re-encoding image " + "data", e2);
        }
      }
      ExternalImage externalImage = new ExternalImage(image, localizedImage, rect);
      shared.externalImages.put(new BundleKey(image, true), externalImage);
      displayed = externalImage;
    }

    if (image.isFlipRtl()) {
      displayed.setRtlImage(localizedImage);
    }
  }

  /**
   * Helper method to read the contentLength of a given URL, automatically
   * closing the InputStream that is opened as a side effect.
   */
  private int getContentLength(URL url) throws IOException {
    URLConnection conn = url.openConnection();
    try {
      return conn.getContentLength();
    } finally {
      Utility.close(conn.getInputStream());
    }
  }

  /**
   * Creates a cache key to be used with {@link ResourceContext#putCachedData}.
   * The key is based on the ClientBundle type, support for data URLs, and the
   * current locale.
   */
  private String createCacheKey(ResourceContext context) {
    StringBuilder sb = new StringBuilder();
    sb.append(context.getClientBundleType().getQualifiedSourceName());
    sb.append(":").append(context.supportsDataUrls());
    try {
      String locale = context.getGeneratorContext().getPropertyOracle().getSelectionProperty(
          TreeLogger.NULL, "locale").getCurrentValue();

      // add the locale selection property as a permuation axis for our requirements
      context.getRequirements().addPermutationAxis("locale");

      sb.append(locale);
    } catch (BadPropertyValueException e) {
      // OK, locale isn't defined
    }

    return sb.toString();
  }

  private DisplayedImage getImage(ImageResourceDeclaration image) {
    DisplayedImage toReturn = shared.externalImages.get(new BundleKey(image, true));
    if (toReturn != null) {
      return toReturn;
    }

    BundleKey key = new BundleKey(image, false);
    toReturn = shared.bundledImages.get(key);
    if (toReturn == null) {
      BundledImage bundled = new BundledImage();
      shared.bundledImages.put(key, bundled);
      toReturn = bundled;
    }

    return toReturn;
  }

  /**
   * Re-encode an image as a PNG to strip random header data.
   */
  private URL reencodeToTempFile(TreeLogger logger, ImageRect rect)
      throws UnableToCompleteException {
    try {
      byte[] imageBytes = ImageBundleBuilder.toPng(logger, rect);

      if (imageBytes == null) {
        return null;
      }

      File file = File.createTempFile(ImageResourceGenerator.class.getSimpleName(), ".png");
      file.deleteOnExit();
      Util.writeBytesToFile(logger, file, imageBytes);
      return file.toURI().toURL();
    } catch (IOException ex) {
      logger.log(TreeLogger.ERROR, "Unable to write re-encoded PNG", ex);
      throw new UnableToCompleteException();
    }
  }

  private void renderImageMap(TreeLogger logger, ResourceContext context,
      ClientBundleFields fields, Map<BundleKey, ? extends DisplayedImage> map)
      throws UnableToCompleteException {
    for (Map.Entry<BundleKey, ? extends DisplayedImage> entry : map.entrySet()) {
      DisplayedImage bundle = entry.getValue();
      bundle.render(logger, context, fields, entry.getKey().getRepeatStyle());
    }
  }
}
