/*
 * 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.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.resources.ext.ResourceContext;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

/**
 * Accumulates state for the bundled image.
 */
class ImageBundleBuilder {
  /**
   * Abstracts the process of arranging a number of images into a composite
   * image.
   */
  interface Arranger {
    /**
     * Determine the total area required to store a composite image.
     */
    Size arrangeImages(Collection<HasRect> rects);
  }

  /**
   * Arranges the images to try to decrease the overall area of the resulting
   * bundle. This uses a strategy that is basically Next-Fit Decreasing Height
   * Decreasing Width (NFDHDW). The rectangles to be packed are sorted in
   * decreasing order by height. The tallest rectangle is placed at the far
   * left. We attempt to stack the remaining rectangles on top of one another to
   * construct as many columns as necessary. After finishing each column, we
   * also attempt to do some horizontal packing to fill up the space left due to
   * widths of rectangles differing in the column.
   */
  static class BestFitArranger implements Arranger {
    private static final Comparator<HasRect> decreasingHeightComparator = new Comparator<HasRect>() {
      public int compare(HasRect a, HasRect b) {
        final int c = b.getHeight() - a.getHeight();
        // If we encounter equal heights, use the name to keep things
        // deterministic.
        return (c != 0) ? c : b.getName().compareTo(a.getName());
      }
    };

    private static final Comparator<HasRect> decreasingWidthComparator = new Comparator<HasRect>() {
      public int compare(HasRect a, HasRect b) {
        final int c = b.getWidth() - a.getWidth();
        // If we encounter equal heights, use the name to keep things
        // deterministic.
        return (c != 0) ? c : b.getName().compareTo(a.getName());
      }
    };

    public Size arrangeImages(Collection<HasRect> rects) {
      if (rects.size() == 0) {
        return new Size(0, 0);
      }

      // Create a list of ImageRects ordered by decreasing height used for
      // constructing columns.
      final ArrayList<HasRect> rectsOrderedByHeight = new ArrayList<HasRect>(
          rects);
      Collections.sort(rectsOrderedByHeight, decreasingHeightComparator);

      // Create a list of ImageRects ordered by decreasing width used for
      // packing
      // individual columns.
      final ArrayList<HasRect> rectsOrderedByWidth = new ArrayList<HasRect>(
          rects);
      Collections.sort(rectsOrderedByWidth, decreasingWidthComparator);

      // Place the first, tallest image as the first column.
      final HasRect first = rectsOrderedByHeight.get(0);
      first.setPosition(0, 0);

      // Setup state for laying things cumulatively.
      int curX = first.getWidth();
      final int colH = first.getHeight();

      for (int i = 1, n = rectsOrderedByHeight.size(); i < n; i++) {
        // If this ImageRect has been positioned already, move on.
        if (rectsOrderedByHeight.get(i).hasBeenPositioned()) {
          continue;
        }

        int colW = 0;
        int curY = 0;

        final ArrayList<HasRect> rectsInColumn = new ArrayList<HasRect>();
        for (int j = i; j < n; j++) {
          final HasRect current = rectsOrderedByHeight.get(j);
          // Look for rects that have not been positioned with a small enough
          // height to go in this column.
          if (!current.hasBeenPositioned()
              && (curY + current.getHeight()) <= colH) {

            // Set the horizontal position here, the top field will be set in
            // arrangeColumn after we've collected a full set of ImageRects.
            current.setPosition(curX, 0);
            colW = Math.max(colW, current.getWidth());
            curY += current.getHeight();

            // Keep the ImageRects in this column in decreasing order by width.
            final int pos = Collections.binarySearch(rectsInColumn, current,
                decreasingWidthComparator);
            assert pos < 0;
            rectsInColumn.add(-1 - pos, current);
          }
        }

        // Having selected a set of ImageRects that fill out this column
        // vertical,
        // now we'll scan the remaining ImageRects to try to fit some in the
        // horizontal gaps.
        if (!rectsInColumn.isEmpty()) {
          arrangeColumn(rectsInColumn, rectsOrderedByWidth);
        }

        // We're done with that column, so move the horizontal accumulator by
        // the
        // width of the column we just finished.
        curX += colW;
      }

      return new Size(curX, colH);
    }

    /**
     * Companion method to {@link #arrangeImages()}. This method does a best
     * effort horizontal packing of a column after it was packed vertically.
     * This is the Decreasing Width part of Next-Fit Decreasing Height
     * Decreasing Width. The basic strategy is to sort the remaining rectangles
     * by decreasing width and try to fit them to the left of each of the
     * rectangles we've already picked for this column.
     * 
     * @param rectsInColumn the ImageRects that were already selected for this
     *          column
     * @param remainingRectsOrderedByWidth the sub list of ImageRects that may
     *          not have been positioned yet
     */
    private void arrangeColumn(List<HasRect> rectsInColumn,
        List<HasRect> remainingRectsOrderedByWidth) {
      final HasRect first = rectsInColumn.get(0);

      final int columnWidth = first.getWidth();
      int curY = first.getHeight();

      // Skip this first ImageRect because it is guaranteed to consume the full
      // width of the column.
      for (int i = 1, m = rectsInColumn.size(); i < m; i++) {
        final HasRect r = rectsInColumn.get(i);
        // The ImageRect was previously positioned horizontally, now set the top
        // field.
        r.setPosition(r.getLeft(), curY);
        int curX = r.getWidth();

        // Search for ImageRects that are shorter than the left most ImageRect
        // and
        // narrow enough to fit in the column.
        for (int j = 0, n = remainingRectsOrderedByWidth.size(); j < n; j++) {
          final HasRect current = remainingRectsOrderedByWidth.get(j);
          if (!current.hasBeenPositioned()
              && (curX + current.getWidth()) <= columnWidth
              && (current.getHeight() <= r.getHeight())) {
            current.setPosition(r.getLeft() + curX, r.getTop());
            curX += current.getWidth();
          }
        }

        // Update the vertical accumulator so we'll know where to place the next
        // ImageRect.
        curY += r.getHeight();
      }
    }
  }

  /**
   * A mockable interface to test the image arrangement algorithms.
   */
  interface HasRect {

    int getHeight();

    BufferedImage getImage();

    int getLeft();

    String getName();

    int getTop();

    AffineTransform getTransform();

    int getWidth();

    boolean hasBeenPositioned();

    void setPosition(int left, int top);

    AffineTransform transform();
  }

  /**
   * Performs a simple horizontal arrangement of rectangles. Images will be
   * tiled vertically to fill to fill the full height of the image.
   */
  static class HorizontalArranger implements Arranger {
    public Size arrangeImages(Collection<HasRect> rects) {
      int height = 1;
      int width = 0;

      for (HasRect rect : rects) {
        rect.setPosition(width, 0);
        width += rect.getWidth();
        height = lcm(height, rect.getHeight());
      }

      List<HasRect> toAdd = new ArrayList<HasRect>();
      for (HasRect rect : rects) {
        int y = rect.getHeight();
        while (y < height) {
          ImageRect newRect = new ImageRect(rect);
          newRect.setPosition(rect.getLeft(), y);
          y += rect.getHeight();
          toAdd.add(newRect);
        }
      }
      rects.addAll(toAdd);

      return new Size(width, height);
    }
  }

  /**
   * Does not rearrange the rectangles, but simply computes the size of the
   * canvas needed to hold the images in their current positions.
   */
  static class IdentityArranger implements Arranger {
    public Size arrangeImages(Collection<HasRect> rects) {
      int height = 0;
      int width = 0;

      for (HasRect rect : rects) {
        height = Math.max(height, rect.getTop() + rect.getHeight());
        width = Math.max(width, rect.getLeft() + rect.getWidth());
      }

      return new Size(width, height);
    }
  }

  /**
   * The rectangle at which the original image is placed into the composite
   * image.
   */
  static class ImageRect implements HasRect {

    private boolean hasBeenPositioned;
    private final int height, width;
    private final BufferedImage image;
    private int left, top;
    private final String name;
    private final AffineTransform transform = new AffineTransform();

    /**
     * Copy constructor.
     */
    public ImageRect(HasRect other) {
      this.name = other.getName();
      this.height = other.getHeight();
      this.width = other.getWidth();
      this.image = other.getImage();
      this.left = other.getLeft();
      this.top = other.getTop();
      setTransform(other.getTransform());
    }

    public ImageRect(String name, BufferedImage image) {
      this.name = name;
      this.image = image;
      this.width = image.getWidth();
      this.height = image.getHeight();
    }

    public int getHeight() {
      return height;
    }

    public BufferedImage getImage() {
      return image;
    }

    public int getLeft() {
      return left;
    }

    public String getName() {
      return name;
    }

    public int getTop() {
      return top;
    }

    public AffineTransform getTransform() {
      return new AffineTransform(transform);
    }

    public int getWidth() {
      return width;
    }

    public boolean hasBeenPositioned() {
      return hasBeenPositioned;
    }

    public void setPosition(int left, int top) {
      hasBeenPositioned = true;
      this.left = left;
      this.top = top;
    }

    public void setTransform(AffineTransform transform) {
      this.transform.setTransform(transform);
    }

    public AffineTransform transform() {
      AffineTransform toReturn = new AffineTransform();
      toReturn.translate(left, top);
      toReturn.concatenate(transform);

      assert checkTransform(toReturn);
      return toReturn;
    }

    private boolean checkTransform(AffineTransform tx) {
      double[] in = {0, 0, width, height};
      double[] out = {0, 0, 0, 0};

      tx.transform(in, 0, out, 0, 2);

      assert width == Math.abs(out[0] - out[2]);
      assert height == Math.abs(out[1] - out[3]);
      assert out[0] >= 0;
      assert out[1] >= 0;
      assert out[2] >= 0;
      assert out[3] >= 0;

      return true;
    }
  }

  /**
   * Used to return the size of the resulting image from the method
   * {@link ImageBundleBuilder#arrangeImages()}.
   */
  static class Size {
    private final int width, height;

    Size(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }

  /**
   * Performs a simple vertical arrangement of rectangles. Images will be tiled
   * horizontally to fill the full width of the image.
   */
  static class VerticalArranger implements Arranger {
    public Size arrangeImages(Collection<HasRect> rects) {
      int height = 0;
      int width = 1;

      for (HasRect rect : rects) {
        rect.setPosition(0, height);
        width = lcm(width, rect.getWidth());
        height += rect.getHeight();
      }

      List<HasRect> toAdd = new ArrayList<HasRect>();
      for (HasRect rect : rects) {
        int x = rect.getWidth();
        while (x < width) {
          ImageRect newRect = new ImageRect(rect);
          newRect.setPosition(x, rect.getTop());
          x += rect.getWidth();
          toAdd.add(newRect);
        }
      }
      rects.addAll(toAdd);

      return new Size(width, height);
    }
  }

  /*
   * Only PNG is supported right now. In the future, we may be able to infer the
   * best output type, and get rid of this constant.
   */
  private static final String BUNDLE_FILE_TYPE = "png";
  private static final String BUNDLE_MIME_TYPE = "image/png";
  private static final int IMAGE_MAX_SIZE = 256;

  public static byte[] toPng(TreeLogger logger, HasRect rect)
      throws UnableToCompleteException {
    // Create the bundled image.
    BufferedImage bundledImage = new BufferedImage(rect.getWidth(),
        rect.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
    Graphics2D g2d = bundledImage.createGraphics();

    g2d.drawImage(rect.getImage(), rect.transform(), null);
    g2d.dispose();

    byte[] imageBytes;

    try {
      ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
      ImageIO.write(bundledImage, BUNDLE_FILE_TYPE, byteOutputStream);
      imageBytes = byteOutputStream.toByteArray();
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR,
          "Unable to generate file name for image bundle file", null);
      throw new UnableToCompleteException();
    }
    return imageBytes;
  }

  /**
   * Compute the greatest common denominator of two numbers.
   */
  private static int gcd(int a, int b) {
    while (b != 0) {
      int t = b;
      b = a % b;
      a = t;
    }
    return a;
  }

  /**
   * Compute the least common multiple of two numbers. This is used by
   * {@link HorizontalArranger} and {@link VerticalArranger} to determine how
   * large the composite image should be to allow every image to line up when
   * repeated.
   */
  private static int lcm(int a, int b) {
    return b / gcd(a, b) * a;
  }

  private final Map<String, ImageRect> imageNameToImageRectMap = new HashMap<String, ImageRect>();

  public ImageBundleBuilder() {
  }

  /**
   * Copy constructor.
   */
  public ImageBundleBuilder(ImageBundleBuilder other) {
    for (Map.Entry<String, ImageRect> entry : other.imageNameToImageRectMap.entrySet()) {
      imageNameToImageRectMap.put(entry.getKey(), new ImageRect(
          entry.getValue()));
    }
  }

  /**
   * Assimilates the image associated with a particular image method into the
   * master composite. If the method names an image that has already been
   * assimilated, the existing image rectangle is reused.
   * 
   * @param logger a hierarchical logger which logs to the hosted console
   * @param imageName the name of an image that can be found on the classpath
   * @param resource the URL from which the image data wil be loaded
   * @throws UnableToCompleteException if the image with name
   *           <code>imageName</code> cannot be added to the master composite
   *           image
   */
  public ImageRect assimilate(TreeLogger logger, String imageName, URL resource)
      throws UnableToCompleteException, UnsuitableForStripException {

    /*
     * Decide whether or not we need to add to the composite image. Either way,
     * we associated it with the rectangle of the specified image as it exists
     * within the composite image. Note that the coordinates of the rectangle
     * aren't computed until the composite is written.
     */
    ImageRect rect = getMapping(imageName);
    if (rect == null) {
      // Assimilate the image into the composite.
      rect = addImage(logger, imageName, resource);

      imageNameToImageRectMap.put(imageName, rect);
    }
    return rect;
  }

  public int getImageCount() {
    return imageNameToImageRectMap.size();
  }

  public ImageRect getMapping(String imageName) {
    return imageNameToImageRectMap.get(imageName);
  }

  public ImageRect removeMapping(String imageName) {
    return imageNameToImageRectMap.remove(imageName);
  }

  /**
   * Write all images into the output.
   * 
   * @param logger a hierarchical logger which logs to the hosted console
   * @param context the local ResourceContext that is being used to accumulate
   *          output files
   * @param arranger a provider of image layout logic
   * @return a Java expression which will evaluate to the location of the
   *         composite image at runtime
   */
  public String writeBundledImage(TreeLogger logger, ResourceContext context,
      Arranger arranger) throws UnableToCompleteException {

    if (imageNameToImageRectMap.isEmpty()) {
      return null;
    }

    // Create the bundled image from all of the constituent images.
    BufferedImage bundledImage = drawBundledImage(arranger);

    // Write the bundled image into a byte array, so that we can compute
    // its strong name.
    byte[] imageBytes;

    try {
      ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
      ImageIO.write(bundledImage, BUNDLE_FILE_TYPE, byteOutputStream);
      imageBytes = byteOutputStream.toByteArray();
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR,
          "Unable to generate file name for image bundle file", null);
      throw new UnableToCompleteException();
    }

    String bundleFileName = context.deploy(
        context.getClientBundleType().getQualifiedSourceName() + ".cache."
            + BUNDLE_FILE_TYPE, BUNDLE_MIME_TYPE, imageBytes, false);

    return bundleFileName;
  }

  private ImageRect addImage(TreeLogger logger, String imageName, URL imageUrl)
      throws UnableToCompleteException, UnsuitableForStripException {

    logger = logger.branch(TreeLogger.TRACE,
        "Adding image '" + imageName + "'", null);

    BufferedImage image;
    // Load the image
    try {
      image = ImageIO.read(imageUrl);
    } catch (IllegalArgumentException iex) {
      if (imageName.toLowerCase().endsWith("png")
          && iex.getMessage() != null
          && iex.getStackTrace()[0].getClassName().equals(
              "javax.imageio.ImageTypeSpecifier$Indexed")) {
        logger.log(TreeLogger.ERROR,
            "Unable to read image. The image may not be in valid PNG format. "
                + "This problem may also be due to a bug in versions of the "
                + "JRE prior to 1.6. See "
                + "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5098176 "
                + "for more information. If this bug is the cause of the "
                + "error, try resaving the image using a different image "
                + "program, or upgrade to a newer JRE.", null);
        throw new UnableToCompleteException();
      } else {
        throw iex;
      }
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR, "Unable to read image resource", null);
      throw new UnableToCompleteException();
    }

    if (image == null) {
      logger.log(TreeLogger.ERROR, "Unrecognized image file format", null);
      throw new UnableToCompleteException();
    }

    ImageRect toReturn = new ImageRect(imageName, image);

    if (toReturn.height > IMAGE_MAX_SIZE || toReturn.width > IMAGE_MAX_SIZE) {
      throw new UnsuitableForStripException(toReturn);
    }

    return toReturn;
  }

  /**
   * This method creates the bundled image through the composition of the other
   * images.
   * 
   * In this particular implementation, we use NFDHDW (see
   * {@link #arrangeImages()}) to get an approximate optimal image packing.
   * 
   * The most important aspect of drawing the bundled image is that it be drawn
   * in a deterministic way. The drawing of the image should not rely on
   * implementation details of the Generator system which may be subject to
   * change.
   */
  private BufferedImage drawBundledImage(Arranger arranger) {

    /*
     * There is no need to impose any order here, because arrangeImages will
     * position the ImageRects in a deterministic fashion, even though we might
     * paint them in a non-deterministic order.
     */
    Collection<HasRect> imageRects = new LinkedList<HasRect>(
        imageNameToImageRectMap.values());

    // Arrange images and determine the size of the resulting bundle.
    Size size = arranger.arrangeImages(imageRects);

    // Create the bundled image.
    BufferedImage bundledImage = new BufferedImage(size.width, size.height,
        BufferedImage.TYPE_INT_ARGB_PRE);
    Graphics2D g2d = bundledImage.createGraphics();

    for (HasRect imageRect : imageRects) {
      g2d.drawImage(imageRect.getImage(), imageRect.transform(), null);
    }
    g2d.dispose();

    return bundledImage;
  }
}
