/*
 * 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.event.ThrowableLogEvent;
import com.facebook.buck.shell.BashStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.util.DefaultFilteredDirectoryCopier;
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.MorePaths;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
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 com.google.common.collect.Lists;

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

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

  @VisibleForTesting
  static final Pattern NON_ENGLISH_STRING_PATH = Pattern.compile(
      "(\\b|.*/)res/values-.+/strings.xml", Pattern.CASE_INSENSITIVE);

  private final ImmutableBiMap<String, String> inResDirToOutResDirMap;
  private final boolean filterDrawables;
  private final boolean filterStrings;
  private final FilteredDirectoryCopier filteredDirectoryCopier;
  @Nullable
  private final String resourceFilter;
  @Nullable
  private final DrawableFinder drawableFinder;
  @Nullable
  private final ImageScaler imageScaler;
  private final ImmutableSet.Builder<String> nonEnglishStringFilesBuilder;

  /**
   * Creates a command that filters a specified set of directories.
   * @param inResDirToOutResDirMap set of {@code res} directories to filter
   * @param filterDrawables whether to filter drawables (images)
   * @param filterStrings whether to filter non-english strings
   * @param filteredDirectoryCopier refer {@link FilteredDirectoryCopier}
   *
   * @param resourceFilter filtering to perform (currently based on density; allowed values are
   *     {@code "mdpi"}, {@code "hdpi"} and {@code "xhdpi"}). Only applicable if filterDrawables
   *     is true
   * @param drawableFinder refer {@link DrawableFinder}. Only applicable if filterDrawables is true.
   * @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). Only applicable if filterDrawables. is true.
   */
  @VisibleForTesting
  FilterResourcesStep(
      ImmutableBiMap<String, String> inResDirToOutResDirMap,
      boolean filterDrawables,
      boolean filterStrings,
      FilteredDirectoryCopier filteredDirectoryCopier,
      @Nullable String resourceFilter,
      @Nullable DrawableFinder drawableFinder,
      @Nullable ImageScaler imageScaler) {

    Preconditions.checkArgument(filterDrawables || filterStrings);
    Preconditions.checkArgument(!filterDrawables ||
        (resourceFilter != null && drawableFinder != null));
    this.inResDirToOutResDirMap = Preconditions.checkNotNull(inResDirToOutResDirMap);
    this.filterDrawables = filterDrawables;
    this.filterStrings = filterStrings;
    this.filteredDirectoryCopier = Preconditions.checkNotNull(filteredDirectoryCopier);

    this.resourceFilter = resourceFilter;
    this.drawableFinder = drawableFinder;
    this.imageScaler = imageScaler;
    this.nonEnglishStringFilesBuilder = ImmutableSet.builder();
  }

  @Override
  public int execute(ExecutionContext context) {
    try {
      return doExecute(context);
    } catch (Exception e) {
      context.getBuckEventBus().post(ThrowableLogEvent.create(e,
          "There was an error filtering resources."));
      return 1;
    }
  }

  /**
   * @return If {@code filterStrings} is true, set containing absolute file paths to non-english
   * string files, matching NON_ENGLISH_STRING_PATH regex; else empty set.
   */
  public ImmutableSet<String> getNonEnglishStringFiles() {
    return nonEnglishStringFilesBuilder.build();
  }

  private int doExecute(ExecutionContext context) throws IOException {
    List<Predicate<File>> filePredicates = Lists.newArrayList();
    if (filterDrawables) {
      Set<String> drawables = drawableFinder.findDrawables(inResDirToOutResDirMap.keySet());
      filePredicates.add(Filters.createImageDensityFilter(drawables, resourceFilter));
    }

    if (filterStrings) {
      filePredicates.add(new Predicate<File>() {
        @Override
        public boolean apply(File input) {
          String inputPath = input.getAbsolutePath();
          if (NON_ENGLISH_STRING_PATH.matcher(inputPath).matches()) {
            nonEnglishStringFilesBuilder.add(inputPath);
            return false;
          }
          return true;
        }
      });
    }


    // Create filtered copies of all resource directories. These will be passed to aapt instead.
    filteredDirectoryCopier.copyDirs(inResDirToOutResDirMap, Predicates.and(filePredicates));

    // If an ImageScaler was specified, but only if it is available, try to apply it.
    if ((imageScaler != null) && imageScaler.isAvailable(context)) {
      scaleUnmatchedDrawables(context);
    }

    return 0;
  }

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

  @Override
  public String getDescription(ExecutionContext context) {
    return "Filtering drawable and string resources.";
  }

  @VisibleForTesting
  String getResourceFilter() {
    return resourceFilter;
  }

  @VisibleForTesting
  boolean isFilterStrings() {
    return filterStrings;
  }

  @VisibleForTesting
  ImmutableBiMap<String, String> getInResDirToOutResDirMap() {
    return inResDirToOutResDirMap;
  }

  /**
   * 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(inResDirToOutResDirMap.values())) {
      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) throws IOException;
  }

  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) throws IOException {
      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()) {
              // The path is normalized so that the value can be matched against patterns.
              drawableBuilder.add(MorePaths.newPathInstance(file).toString());
            }
          }
        }.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();
    }
  }

  public static Builder builder() {
    return new Builder();
  }

  public static class Builder {

    private ImmutableBiMap<String, String> inResDirToOutResDirMap;
    private ResourceFilter resourceFilter;
    private boolean filterStrings = false;

    private Builder() {
    }

    public Builder setInResToOutResDirMap(ImmutableBiMap<String, String> inResDirToOutResDirMap) {
      this.inResDirToOutResDirMap = inResDirToOutResDirMap;
      return this;
    }

    public Builder setResourceFilter(ResourceFilter resourceFilter) {
      this.resourceFilter = resourceFilter;
      return this;
    }

    public Builder enableStringsFilter() {
      this.filterStrings = true;
      return this;
    }

    public FilterResourcesStep build() {
      return new FilterResourcesStep(
          inResDirToOutResDirMap,
          resourceFilter.isEnabled(),
          filterStrings,
          DefaultFilteredDirectoryCopier.getInstance(),
          resourceFilter.getDensity(),
          DefaultDrawableFinder.getInstance(),
          resourceFilter.shouldDownscale() ? ImageMagickScaler.getInstance() : null);
    }
  }
}
