// Copyright 2015 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.android;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Predicate;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Ordering;
import com.google.devtools.build.android.AndroidResourceMerger.MergingException;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
import javax.annotation.Nullable;

/** Filters a {@link MergedAndroidData} resource drawables to the specified densities. */
public class DensitySpecificResourceFilter {
  private static class ResourceInfo {
    /** Path to an actual file resource, instead of a directory. */
    private Path resource;

    private String restype;
    private String qualifiers;
    private String density;
    private String resid;

    public ResourceInfo(
        Path resource, String restype, String qualifiers, String density, String resid) {
      this.resource = resource;
      this.restype = restype;
      this.qualifiers = qualifiers;
      this.density = density;
      this.resid = resid;
    }

    public Path getResource() {
      return this.resource;
    }

    public String getRestype() {
      return this.restype;
    }

    public String getQualifiers() {
      return this.qualifiers;
    }

    public String getDensity() {
      return this.density;
    }

    public String getResid() {
      return this.resid;
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("resource", resource)
          .add("restype", restype)
          .add("qualifiers", qualifiers)
          .add("density", density)
          .add("resid", resid)
          .toString();
    }
  }

  private static class RecursiveFileCopier extends SimpleFileVisitor<Path> {
    private final Path copyToPath;
    private final List<Path> copiedSourceFiles = new ArrayList<>();
    private Path root;

    public RecursiveFileCopier(final Path copyToPath, final Path root) {
      this.copyToPath = copyToPath;
      this.root = root;
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
      Path copyTo = copyToPath.resolve(root.relativize(path));
      Files.createDirectories(copyTo.getParent());
      Files.copy(path, copyTo, LinkOption.NOFOLLOW_LINKS);
      copiedSourceFiles.add(copyTo);
      return FileVisitResult.CONTINUE;
    }

    public List<Path> getCopiedFiles() {
      return copiedSourceFiles;
    }
  }

  private final List<String> densities;
  private final Path out;
  private final Path working;

  private static final ImmutableMap<String, Integer> DENSITY_MAP =
      new ImmutableMap.Builder<String, Integer>()
          .put("nodpi", 0)
          .put("ldpi", 120)
          .put("mdpi", 160)
          .put("tvdpi", 213)
          .put("hdpi", 240)
          .put("280dpi", 280)
          .put("xhdpi", 320)
          .put("340dpi", 340)
          .put("400dpi", 400)
          .put("420dpi", 420)
          .put("xxhdpi", 480)
          .put("560dpi", 560)
          .put("xxxhdpi", 640)
          .build();

  private static final Function<ResourceInfo, String> GET_RESOURCE_ID =
      new Function<ResourceInfo, String>() {
        @Override
        public String apply(ResourceInfo info) {
          return info.getResid();
        }
      };

  private static final Function<ResourceInfo, String> GET_RESOURCE_QUALIFIERS =
      new Function<ResourceInfo, String>() {
        @Override
        public String apply(ResourceInfo info) {
          return info.getQualifiers();
        }
      };

  private static final Function<ResourceInfo, Path> GET_RESOURCE_PATH =
      new Function<ResourceInfo, Path>() {
        @Override
        public Path apply(ResourceInfo info) {
          return info.getResource();
        }
      };

  /**
   * @param densities An array of string densities to use for filtering resources
   * @param out The path to use for name spacing the final resource directory.
   * @param working The path of the working directory for the filtering
   */
  public DensitySpecificResourceFilter(List<String> densities, Path out, Path working)
      throws MergingException {
    this.densities = densities;
    this.out = out;
    this.working = working;

    for (String density : densities) {
      if (!DENSITY_MAP.containsKey(density)) {
        throw MergingException.withMessage(density + " is not a known density qualifier.");
      }
    }
  }

  @VisibleForTesting
  List<Path> getResourceToRemove(List<Path> resourcePaths) {
    Predicate<ResourceInfo> requestedDensityFilter =
        new Predicate<ResourceInfo>() {
          @Override
          public boolean apply(@Nullable ResourceInfo info) {
            return !densities.contains(info.getDensity());
          }
        };

    List<ResourceInfo> resourceInfos = getResourceInfos(resourcePaths);
    List<ResourceInfo> densityResourceInfos = filterDensityResourceInfos(resourceInfos);
    List<ResourceInfo> resourceInfoToRemove = new ArrayList<>();

    Multimap<String, ResourceInfo> fileGroups =
        groupResourceInfos(densityResourceInfos, GET_RESOURCE_ID);

    for (String key : fileGroups.keySet()) {
      Multimap<String, ResourceInfo> qualifierGroups =
          groupResourceInfos(fileGroups.get(key), GET_RESOURCE_QUALIFIERS);

      for (String qualifiers : qualifierGroups.keySet()) {
        Collection<ResourceInfo> qualifierResourceInfos = qualifierGroups.get(qualifiers);

        if (qualifierResourceInfos.size() != 1) {
          List<ResourceInfo> sortedResourceInfos =
              Ordering.natural()
                  .onResultOf(
                      new Function<ResourceInfo, Double>() {
                        @Override
                        public Double apply(ResourceInfo info) {
                          return matchScore(info, densities);
                        }
                      })
                  .immutableSortedCopy(qualifierResourceInfos);
          resourceInfoToRemove.addAll(
              Collections2.filter(
                  sortedResourceInfos.subList(1, sortedResourceInfos.size()),
                  requestedDensityFilter));
        }
      }
    }

    return ImmutableList.copyOf(Lists.transform(resourceInfoToRemove, GET_RESOURCE_PATH));
  }

  private static void removeResources(List<Path> resourceInfoToRemove) {
    for (Path resource : resourceInfoToRemove) {
      resource.toFile().delete();
    }
  }

  private static Multimap<String, ResourceInfo> groupResourceInfos(
      final Collection<ResourceInfo> resourceInfos, Function<ResourceInfo, String> keyFunction) {
    Multimap<String, ResourceInfo> resourceGroups = ArrayListMultimap.create();

    for (ResourceInfo resourceInfo : resourceInfos) {
      resourceGroups.put(keyFunction.apply(resourceInfo), resourceInfo);
    }

    return ImmutableMultimap.copyOf(resourceGroups);
  }

  private static List<ResourceInfo> getResourceInfos(final List<Path> resourcePaths) {
    List<ResourceInfo> resourceInfos = new ArrayList<>();

    for (Path resourcePath : resourcePaths) {
      String qualifiers = resourcePath.getParent().getFileName().toString();
      String density = "";

      for (String densityName : DENSITY_MAP.keySet()) {
        if (qualifiers.contains("-" + densityName)) {
          qualifiers = qualifiers.replace("-" + densityName, "");
          density = densityName;
        }
      }

      String[] qualifierArray = qualifiers.split("-");
      String restype = qualifierArray[0];
      qualifiers =
          (qualifierArray.length) > 0
              ? Joiner.on("-").join(Arrays.copyOfRange(qualifierArray, 1, qualifierArray.length))
              : "";
      resourceInfos.add(
          new ResourceInfo(
              resourcePath, restype, qualifiers, density, resourcePath.getFileName().toString()));
    }

    return ImmutableList.copyOf(resourceInfos);
  }

  private static List<ResourceInfo> filterDensityResourceInfos(
      final List<ResourceInfo> resourceInfos) {
    List<ResourceInfo> densityResourceInfos = new ArrayList<>();

    for (ResourceInfo info : resourceInfos) {
      if (info.getRestype().equals("drawable")
          && !info.getDensity().equals("")
          && !info.getDensity().equals("nodpi")
          && !info.getResid().endsWith(".xml")) {
        densityResourceInfos.add(info);
      }
    }

    return ImmutableList.copyOf(densityResourceInfos);
  }

  private static double matchScore(ResourceInfo resource, List<String> densities) {
    double score = 0;
    for (String density : densities) {
      score += computeAffinity(DENSITY_MAP.get(resource.getDensity()), DENSITY_MAP.get(density));
    }
    return score;
  }

  private static double computeAffinity(int resourceDensity, int density) {
    if (resourceDensity == density) {
      // Exact match is the best.
      return -2;
    } else if (resourceDensity == 2 * density) {
      // It's very efficient to downsample an image that's exactly 2x the screen
      // density, so we prefer that over other non-perfect matches.
      return -1;
    } else {
      double affinity = Math.log((double) density / resourceDensity) / Math.log(2);

      // We give a slight bump to images that have the same multiplier but are higher quality.
      if (affinity < 0) {
        affinity = Math.abs(affinity) - 0.01;
      }
      return affinity;
    }
  }

  /** Filters the contents of a resource directory. */
  public Path filter(Path unFilteredResourceDir) {
    // no densities to filter, so skip.
    if (densities.isEmpty()) {
      return unFilteredResourceDir;
    }
    final Path filteredResourceDir = out.resolve(working.relativize(unFilteredResourceDir));
    RecursiveFileCopier fileVisitor =
        new RecursiveFileCopier(filteredResourceDir, unFilteredResourceDir);
    try {
      Files.walkFileTree(
          unFilteredResourceDir,
          EnumSet.of(FileVisitOption.FOLLOW_LINKS),
          Integer.MAX_VALUE,
          fileVisitor);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    removeResources(getResourceToRemove(fileVisitor.getCopiedFiles()));
    return filteredResourceDir;
  }
}
