/*
 * Copyright 2012-present Facebook, 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.facebook.buck.android;

import com.facebook.buck.shell.BashStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.util.DirectoryTraversal;
import com.facebook.buck.util.Escaper;
import com.facebook.buck.util.FilteredDirectoryCopier;
import com.facebook.buck.util.Filters;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;

import javax.annotation.Nullable;

/**
 * This {@link com.facebook.buck.step.Step} copies {@code res} directories to a different location,
 * while filtering out certain resources.
 */
public class FilterResourcesStep implements Step {

  /**
   * We use this to compute scaling factors between different densities.
   */
  private static Map<String, Double> DPI_VALUES = ImmutableMap.of(
      "mdpi", 160.0,
      "hdpi", 240.0,
      "xhdpi", 320.0);

  private static final Pattern DRAWABLE_PATH_PATTERN = Pattern.compile(
      ".*drawable.*/.*(png|jpg|jpeg|gif)", Pattern.CASE_INSENSITIVE);

  private final File baseDestination;
  private final String resourceFilter;
  private final FilteredDirectoryCopier filteredDirectoryCopier;
  private final DrawableFinder drawableFinder;
  private final ImmutableBiMap<String, String> originalToFiltered;
  @Nullable
  private final ImageScaler imageScaler;

  /**
   * Creates a command that filters a specified set of directories.
   * @param resDirectories set of {@code res} directories to filter
   * @param baseDestination destination directory, where copies of these directories will be placed
   *     (will be created if necessary)
   * @param resourceFilter filtering to perform (currently based on density; allowed values are
   *     {@code "mdpi"}, {@code "hdpi"} and {@code "xhdpi"})
   * @param imageScaler if not null, use the {@link ImageScaler} to downscale higher-density
   *     drawables for which we weren't able to find an image file of the proper density (as opposed
   *     to allowing Android to do it at runtime)
   */
  public FilterResourcesStep(
      Set<String> resDirectories,
      File baseDestination,
      String resourceFilter,
      FilteredDirectoryCopier filteredDirectoryCopier,
      DrawableFinder drawableFinder,
      @Nullable ImageScaler imageScaler) {
    this.baseDestination = Preconditions.checkNotNull(baseDestination);
    this.resourceFilter = Preconditions.checkNotNull(resourceFilter);
    this.filteredDirectoryCopier = Preconditions.checkNotNull(filteredDirectoryCopier);
    this.drawableFinder = Preconditions.checkNotNull(drawableFinder);
    this.originalToFiltered = assignDestinations(
        Preconditions.checkNotNull(resDirectories),
        Preconditions.checkNotNull(baseDestination));
    this.imageScaler = imageScaler;
  }

  private static ImmutableBiMap<String, String> assignDestinations(Set<String> sources, File base) {
    ImmutableBiMap.Builder<String, String> builder = ImmutableBiMap.builder();
    int count = 0;
    for (String source : sources) {
      builder.put(source, new File(base, String.valueOf(count++)).getPath());
    }
    return builder.build();
  }

  /**
   * Returns drop-in set of resource directories for the rest of the build (e.g. {@code aapt}).
   * @return set of directories which, after running {@link #execute(ExecutionContext)},
   *     will contain filtered copies of the resource directories passed on construction.
   */
  public ImmutableSet<String> getFilteredResourceDirectories() {
    // getFilteredResourceDirectories() yields matching destination directories in the same order
    // as the sources, which is relevant to aapt. Adding
    //   return new TreeSet<String>(destinations);
    // here would yield a broken app
    return originalToFiltered.values();
  }

  @Override
  public int execute(ExecutionContext context) {
    // Get list of candidate drawables.
    Set<String> drawables = drawableFinder.findDrawables(originalToFiltered.keySet());
    // Create a filter that removes drawables not of desired density.
    Predicate<File> densityFilter = Filters.createImageDensityFilter(drawables, resourceFilter);
    // Create filtered copies of all resource directories. These will be passed to aapt instead.
    filteredDirectoryCopier.copyDirs(originalToFiltered,
        densityFilter);

    // If an ImageScaler was specified, but only if it is available, try to apply it.
    if ((imageScaler != null) && imageScaler.isAvailable(context)) {
      try {
        scaleUnmatchedDrawables(context);
      } catch (IOException | HumanReadableException e) {
        context.getConsole().printErrorText("Error while scaling drawables: " + e);
        return 1;
      }
    }

    return 0;
  }

  @Override
  public String getShortName() {
    return "resource_filtering";
  }

  @Override
  public String getDescription(ExecutionContext context) {
    return String.format(
        "Filtering %d resource directories into: %s",
        originalToFiltered.size(),
        baseDestination);
  }

  /**
   * Looks through filtered drawables for files not of the target density and replaces them with
   * scaled versions.
   * <p/>
   * Any drawables found by this step didn't have equivalents in the target density. If they are of
   * a higher density, we can replicate what Android does and downscale them at compile-time.
   */
  private void scaleUnmatchedDrawables(ExecutionContext context) throws IOException {
    ProjectFilesystem filesystem = context.getProjectFilesystem();

    // Go over all the images that remain after filtering.
    for (String drawable : drawableFinder.findDrawables(getFilteredResourceDirectories())) {
      File drawableFile = filesystem.getFileForRelativePath(drawable);

      if (drawable.endsWith(".9.png")) {
        // Skip nine-patch for now.
        continue;
      }

      Filters.Qualifiers qualifiers = new Filters.Qualifiers(drawableFile);

      // If the image has a qualifier but it's not the right one.
      if (!qualifiers.density.equals(this.resourceFilter) && !qualifiers.density.isEmpty()) {

        // Replace density qualifier with target density using regular expression to match
        // the qualifier in the context of a path to a drawable.
        String destination = drawable.replaceFirst(
            "((?:^|/)drawable[^/]*-)" + Pattern.quote(qualifiers.density) + "(-|$|/)",
            "$1" + resourceFilter + "$2");

        double factor = DPI_VALUES.get(resourceFilter) / (DPI_VALUES.get(qualifiers.density));
        if (factor > 1.0) {
          // There is no point in up-scaling.
          continue;
        }

        // Make sure destination folder exists and perform downscaling.
        filesystem.createParentDirs(destination);
        imageScaler.scale(factor, drawable, destination, context);

        // Delete source file.
        if (!filesystem.deleteFileAtPath(drawable)) {
          throw new HumanReadableException("Cannot delete file: " + drawable);
        }

        // Delete newly-empty directories to prevent missing resources errors in apkbuilder.
        String parent = drawableFile.getParent();
        if (filesystem.listFiles(parent).length == 0 && !filesystem.deleteFileAtPath(parent)) {
          throw new HumanReadableException("Cannot delete directory: " + parent);
        }

      }
    }
  }

  public interface DrawableFinder {
    public Set<String> findDrawables(Iterable<String> dirs);
  }

  public static class DefaultDrawableFinder implements DrawableFinder {

    private static final DefaultDrawableFinder instance = new DefaultDrawableFinder();

    public static DefaultDrawableFinder getInstance() {
      return instance;
    }

    @Override
    public Set<String> findDrawables(Iterable<String> dirs) {
      final ImmutableSet.Builder<String> drawableBuilder = ImmutableSet.builder();
      for (String dir : dirs) {
        new DirectoryTraversal(new File(dir)) {
          @Override
          public void visit(File file, String relativePath) {
            if (DRAWABLE_PATH_PATTERN.matcher(relativePath).matches()) {
              drawableBuilder.add(file.getPath());
            }
          }
        }.traverse();
      }
      return drawableBuilder.build();
    }
  }

  public interface ImageScaler {
    public boolean isAvailable(ExecutionContext context);
    public void scale(double factor, String source, String destination, ExecutionContext context);
  }

  /**
   * Implementation of {@link ImageScaler} that uses ImageMagick's {@code convert} command.
   *
   * @see <a href="http://www.imagemagick.org/script/index.php">ImageMagick</a>
   */
  public static class ImageMagickScaler implements ImageScaler {

    private static final ImageMagickScaler instance = new ImageMagickScaler();

    public static ImageMagickScaler getInstance() {
      return instance;
    }

    @Override
    public boolean isAvailable(ExecutionContext context) {
      return 0 == new BashStep("which convert").execute(context);
    }

    @Override
    public void scale(double factor, String source, String destination, ExecutionContext context) {
      Step convertStep = new BashStep(
          "convert",
          "-adaptive-resize", (int) (factor * 100) + "%",
          Escaper.escapeAsBashString(source),
          Escaper.escapeAsBashString(destination)
      );

      if (0 != convertStep.execute(context)) {
        throw new HumanReadableException("Cannot scale " + source + " to " + destination);
      }
    }
  }

  public static class ResourceFilter {

    public ResourceFilter(List<String> resourceFilter) {
      this.filter = ImmutableList.copyOf(resourceFilter);
    }

    private final List<String> filter;

    public boolean shouldDownscale() {
      return filter.contains("downscale");
    }

    @Nullable
    public String getDensity() {
      String density = null;
      for (String option : filter) {
        if (Filters.ORDERING.containsKey(option)) {
          if (density == null) {
            density = option;
          } else {
            throw new HumanReadableException("Multiple target densities not supported yet.");
          }
        }
      }
      return density;
    }

    public boolean isEnabled() {
      return getDensity() != null;
    }

    public String getDescription() {
      return filter.toString();
    }
  }

}
