/*
 * 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 java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import java.net.URL;
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();
    }

    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 {
        assert rect != null : "No ImageRect";
        rect.setHeight(image.getScaleHeight());
        rect.setWidth(image.getScaleWidth());
      }
      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();
      }
      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 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 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();

    SourceWriter sw = new StringSourceWriter();
    sw.println("new " + ImageResourcePrototype.class.getName() + "(");
    sw.indent();
    sw.println('"' + name + "\",");

    ImageResourceDeclaration image = new ImageResourceDeclaration(method);
    DisplayedImage bundle = getImage(image);
    ImageRect rect = bundle.getImageRect(image);
    assert rect != null : "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;
      if (image.isPreventInlining()) {
        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 {
          URL contentLocation = localizedImage.getUrl();
          int originalSize = contentLocation.openConnection().getContentLength();

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

          // 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);
    }
  }

  /**
   * 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());
    }
  }
}
