// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;

import com.android.tools.r8.ArchiveClassFileProvider;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.Keep;
import com.android.tools.r8.dexsplitter.DexSplitter.FeatureJar;
import com.android.tools.r8.origin.PathOrigin;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * Provides a mappings of classes to modules. The structure of the input file is as follows:
 * packageOrClass:module
 *
 * <p>Lines with a # prefix are ignored.
 *
 * <p>We will do most specific matching, i.e.,
 * <pre>
 *   com.google.foobar.*:feature2
 *   com.google.*:base
 * </pre>
 * will put everything in the com.google namespace into base, except classes in com.google.foobar
 * that will go to feature2. Class based mappings takes precedence over packages (since they are
 * more specific):
 * <pre>
 *   com.google.A:feature2
 *   com.google.*:base
 *  </pre>
 * Puts A into feature2, and all other classes from com.google into base.
 *
 * <p>Note that this format does not allow specifying inter-module dependencies, this is simply a
 * placement tool.
 */
@Keep
public final class FeatureClassMapping {

  Map<String, String> parsedRules = new HashMap<>(); // Already parsed rules.
  Map<String, String> parseNonClassRules = new HashMap<>();
  boolean usesOnlyExactMappings = true;

  Set<FeaturePredicate> mappings = new HashSet<>();

  Path mappingFile;
  String baseName = DEFAULT_BASE_NAME;

  static final String DEFAULT_BASE_NAME = "base";

  static final String COMMENT = "#";
  static final String SEPARATOR = ":";

  public String getBaseName() {
    return baseName;
  }

  private static class SpecificationOrigin extends PathOrigin {

    public SpecificationOrigin(Path path) {
      super(path);
    }

    @Override
    public String part() {
      return "specification file '" + super.part() + "'";
    }
  }

  private static class JarFileOrigin extends PathOrigin {

    public JarFileOrigin(Path path) {
      super(path);
    }

    @Override
    public String part() {
      return "jar file '" + super.part() + "'";
    }
  }

  public static FeatureClassMapping fromSpecification(Path file) throws FeatureMappingException {
    return fromSpecification(file, new DiagnosticsHandler() {});
  }

  public static FeatureClassMapping fromSpecification(Path file, DiagnosticsHandler reporter)
      throws FeatureMappingException {
    FeatureClassMapping mapping = new FeatureClassMapping();
    List<String> lines = null;
    try {
      lines = FileUtils.readAllLines(file);
    } catch (IOException e) {
      ExceptionDiagnostic error = new ExceptionDiagnostic(e, new SpecificationOrigin(file));
      reporter.error(error);
      throw new AbortException(error);
    }
    for (int i = 0; i < lines.size(); i++) {
      String line = lines.get(i);
      mapping.parseAndAdd(line, i);
    }
    return mapping;
  }

  public static class Internal {
    private static List<String> getClassFileDescriptors(String jar, DiagnosticsHandler reporter) {
      Path jarPath = Paths.get(jar);
      try {
        return new ArchiveClassFileProvider(jarPath).getClassDescriptors()
            .stream()
            .map(DescriptorUtils::descriptorToJavaType)
            .collect(Collectors.toList());
      } catch (IOException e) {
        ExceptionDiagnostic error = new ExceptionDiagnostic(e, new JarFileOrigin(jarPath));
        reporter.error(error);
        throw new AbortException(error);
      }
    }

    private static List<String> getNonClassFiles(String jar, DiagnosticsHandler reporter) {
      try (ZipFile zipfile = new ZipFile(jar, StandardCharsets.UTF_8)) {
          return zipfile.stream()
              .filter(entry -> !ZipUtils.isClassFile(entry.getName()))
              .map(ZipEntry::getName)
              .collect(Collectors.toList());
        } catch (IOException e) {
        ExceptionDiagnostic error = new ExceptionDiagnostic(e, new JarFileOrigin(Paths.get(jar)));
        reporter.error(error);
        throw new AbortException(error);
        }
    }

    public static FeatureClassMapping fromJarFiles(
        List<FeatureJar> featureJars, List<String> baseJars, String baseName,
        DiagnosticsHandler reporter)
        throws FeatureMappingException {
      FeatureClassMapping mapping = new FeatureClassMapping();
      if (baseName != null) {
        mapping.baseName = baseName;
      }
      for (FeatureJar featureJar : featureJars) {
        for (String javaType : getClassFileDescriptors(featureJar.getJar(), reporter)) {
          mapping.addMapping(javaType, featureJar.getOutputName());
        }
        for (String nonClass : getNonClassFiles(featureJar.getJar(), reporter)) {
          mapping.addNonClassMapping(nonClass, featureJar.getOutputName());
        }
      }
      for (String baseJar : baseJars) {
        for (String javaType : getClassFileDescriptors(baseJar, reporter)) {
          mapping.addBaseMapping(javaType);
        }
        for (String nonClass : getNonClassFiles(baseJar, reporter)) {
          mapping.addBaseNonClassMapping(nonClass);
        }
      }
      assert mapping.usesOnlyExactMappings;
      return mapping;
    }

  }

  private FeatureClassMapping() {}

  public void addBaseMapping(String clazz) throws FeatureMappingException {
    addMapping(clazz, baseName);
  }

  public void addBaseNonClassMapping(String name) {
    addNonClassMapping(name, baseName);
  }

  public void addMapping(String clazz, String feature) throws FeatureMappingException {
    addRule(clazz, feature, 0);
  }

  public void addNonClassMapping(String name, String feature) {
    // If a non-class file is present in multiple features put the resource in the base.
    parseNonClassRules.put(name, parseNonClassRules.containsKey(name) ? baseName : feature);
  }

  FeatureClassMapping(List<String> lines) throws FeatureMappingException {
    for (int i = 0; i < lines.size(); i++) {
      String line = lines.get(i);
      parseAndAdd(line, i);
    }
  }

  public String featureForClass(String clazz) {
    if (usesOnlyExactMappings) {
      return parsedRules.getOrDefault(clazz, baseName);
    } else {
      FeaturePredicate bestMatch = null;
      for (FeaturePredicate mapping : mappings) {
        if (mapping.match(clazz)) {
          if (bestMatch == null || bestMatch.predicate.length() < mapping.predicate.length()) {
            bestMatch = mapping;
          }
        }
      }
      if (bestMatch == null) {
        return baseName;
      }
      return bestMatch.feature;
    }
  }

  public String featureForNonClass(String nonClass) {
    return parseNonClassRules.getOrDefault(nonClass, baseName);
  }

  private void parseAndAdd(String line, int lineNumber) throws FeatureMappingException {
    if (line.startsWith(COMMENT)) {
      return; // Ignore comments
    }
    if (line.isEmpty()) {
      return; // Ignore blank lines
    }

    if (!line.contains(SEPARATOR)) {
      error("Mapping lines must contain a " + SEPARATOR, lineNumber);
    }
    String[] values = line.split(SEPARATOR);
    if (values.length != 2) {
      error("Mapping lines can only contain one " + SEPARATOR, lineNumber);
    }

    String predicate = values[0];
    String feature = values[1];
    addRule(predicate, feature, lineNumber);
  }

  private void addRule(String predicate, String feature, int lineNumber)
      throws FeatureMappingException {
    if (parsedRules.containsKey(predicate)) {
      if (!parsedRules.get(predicate).equals(feature)) {
        error("Redefinition of predicate " + predicate + "not allowed", lineNumber);
      }
      return; // Already have this rule.
    }
    parsedRules.put(predicate, feature);
    FeaturePredicate featurePredicate = new FeaturePredicate(predicate, feature);
    mappings.add(featurePredicate);
    usesOnlyExactMappings &= featurePredicate.isExactmapping();
  }

  private void error(String error, int line) throws FeatureMappingException {
    throw new FeatureMappingException(
        "Invalid mappings specification: " + error + "\n in file " + mappingFile + ":" + line);
  }

  @Keep
  public static class FeatureMappingException extends Exception {
    FeatureMappingException(String message) {
      super(message);
    }
  }

  /** A feature predicate can either be a wildcard or class predicate. */
  private static class FeaturePredicate {
    private static Pattern identifier = Pattern.compile("[A-Za-z_\\-][A-Za-z0-9_$\\-]*");
    final String predicate;
    final String feature;
    final boolean isCatchAll;
    // False implies class predicate.
    final boolean isWildcard;

    FeaturePredicate(String predicate, String feature) throws FeatureMappingException {
      isWildcard = predicate.endsWith(".*");
      isCatchAll =  predicate.equals("*");
      if (isCatchAll) {
        this.predicate = "";
      } else if (isWildcard) {
        String packageName = predicate.substring(0, predicate.length() - 2);
        if (!DescriptorUtils.isValidJavaType(packageName)) {
          throw new FeatureMappingException(packageName + " is not a valid identifier");
        }
        // Prefix of a fully-qualified class name, including a terminating dot.
        this.predicate = predicate.substring(0, predicate.length() - 1);
      } else {
        if (!DescriptorUtils.isValidJavaType(predicate)) {
          throw new FeatureMappingException(predicate + " is not a valid identifier");
        }
        this.predicate = predicate;
      }
      this.feature = feature;
    }

    boolean match(String className) {
      if (isCatchAll) {
        return true;
      } else if (isWildcard) {
        return className.startsWith(predicate);
      } else {
        return className.equals(predicate);
      }
    }

    boolean isExactmapping() {
      return !isWildcard && !isCatchAll;
    }
  }
}
