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

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Table;

import java.io.File;
import java.util.Map;
import java.util.Set;

public class Filters {

  // TODO(user): maybe support ldpi in the future. So far it's a non issue. it's implicitly
  // treates as a non-density qualifier because it's not in ORDERING, so it's kept separate of
  // all others. We don't have enough ldpi drawables for this to be worth pursuing right now.

  private static final ImmutableMap<String, ImmutableList<String>> ORDERING = ImmutableMap.of(
      "mdpi", ImmutableList.of("mdpi", "", "hdpi", "xhdpi"),
      "hdpi", ImmutableList.of("hdpi", "xhdpi", "mdpi", ""),
      "xhdpi", ImmutableList.of("xhdpi", "hdpi", "mdpi", "")
  );

  static class Qualifiers {
    public final String density;
    public final String others;

    /**
     * Splits off the density qualifier from a drawable.
     * @param file path to a drawable
     */
    public Qualifiers(File file) {
      StringBuilder densityBuilder = new StringBuilder();
      StringBuilder othersBuilder = new StringBuilder();
      for (String qualifier : file.getParentFile().getName().split("-")) {
        if (qualifier.equals("drawable")) { // We're assuming they're all drawables.
          continue;
        }
        StringBuilder whichBuilder =
            ORDERING.containsKey(qualifier) ? densityBuilder : othersBuilder;
        whichBuilder.append((MoreStrings.isEmpty(whichBuilder) ? "" : "-") + qualifier);
      }
      this.density = densityBuilder.toString();
      this.others = othersBuilder.toString();
    }
  }

  /**
   * Takes a list of image files (as paths), and a target density (mdpi, hdpi, xhdpi), and
   * returns a list of files which can be safely left out when building an APK for phones with that
   * screen density. That APK will run on other screens as well but look worse due to scaling.
   * <p>
   * Each combination of non-density qualifiers is processed separately. For example, if we have
   * {@code drawable-hdpi, drawable-mdpi, drawable-xhdpi, drawable-hdpi-ro}, for a target of {@code
   * mdpi}, we'll be keeping {@code drawable-mdpi, drawable-hdpi-ro}.
   * @param candidates list of paths to image files
   * @param targetDensity density to keep
   * @return set of files to remove
   */
  @VisibleForTesting
  static Set<File> onlyOneImage(Iterable<String> candidates, String targetDensity) {
    ImmutableSet.Builder<File> removals = ImmutableSet.builder();

    Table<String, String, String> imageValues = HashBasedTable.create();

    // Create mappings for drawables. If candidate == "<base>/drawable-<dpi>-<other>/<filename>",
    // then we'll record a mapping of the form ("<base>/<filename>/<other>", "<dpi>") -> candidate.
    for (String candidate : candidates) {
      File f = new File(candidate);

      Qualifiers qualifiers = new Qualifiers(f);

      String filename = f.getName();
      String density = qualifiers.density;
      String resDirectory = f.getParentFile().getParent();
      String key = String.format("%s/%s/%s", resDirectory, filename, qualifiers.others);
      imageValues.put(key, density, candidate);
    }

    for (String key : imageValues.rowKeySet()) {
      Map<String, String> options = imageValues.row(key);
      Set<String> densitiesForKey = options.keySet();

      ImmutableList<String> resOrder = ORDERING.get(targetDensity);

      // If there's only one density, or there are densities we don't work with, skip this image.
      if (options.size() == 1 || !resOrder.containsAll(densitiesForKey)) {
        continue;
      }

      // Go through DPIs in order of preference and keep the first one actually present.
      String keep = resOrder.get(0);
      for (String res : resOrder) {
        if (densitiesForKey.contains(res)) {
          keep = res;
          break;
        }
      }

      // Mark all the others for removal.
      for (String density : densitiesForKey) {
        if (keep.equals(density)) {
          continue;
        }
        removals.add(new File(options.get(density)).getAbsoluteFile());
      }
    }
    return removals.build();
  }

  /**
   * Given a list of paths of available drawables, and a target screen density, returns a
   * {@link com.google.common.base.Predicate} that fails for drawables of a different
   * density, whenever they can be safely removed.
   * @param candidates list of available drawables
   * @param targetDensity one of {@code "xhdpi"}, {@code "hdpi"} or {@code "mdpi"}
   * @return a predicate as above
   */
  public static Predicate<File> createImageDensityFilter(Iterable<String> candidates,
      String targetDensity) {
    Preconditions.checkArgument(ORDERING.containsKey(targetDensity));
    final Set<File> removals = onlyOneImage(candidates, targetDensity);
    return new Predicate<File>() {
      @Override
      public boolean apply(File pathname) {
        return !removals.contains(pathname.getAbsoluteFile());
      }
    };
  }
}
