// 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.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Pattern;
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 {

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

  HashSet<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 = ":";

  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 DefaultDiagnosticsHandler());
  }

  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) {
      reporter.error(new ExceptionDiagnostic(e, new SpecificationOrigin(file)));
      throw new AbortException();
    }
    for (int i = 0; i < lines.size(); i++) {
      String line = lines.get(i);
      mapping.parseAndAdd(line, i);
    }
    return mapping;
  }

  public static class Internal {

    public static FeatureClassMapping fromJarFiles(
        List<FeatureJar> featureJars, String baseName, DiagnosticsHandler reporter)
        throws FeatureMappingException {
      FeatureClassMapping mapping = new FeatureClassMapping();
      if (mapping.baseName != null) {
        mapping.baseName = baseName;
      }
      for (FeatureJar featureJar : featureJars) {
        Path jarPath = Paths.get(featureJar.getJar());
        ArchiveClassFileProvider provider = null;
        try {
          provider = new ArchiveClassFileProvider(jarPath);
        } catch (IOException e) {
          reporter.error(new ExceptionDiagnostic(e, new JarFileOrigin(jarPath)));
          throw new AbortException();
        }
        for (String javaDescriptor : provider.getClassDescriptors()) {
          String javaType = DescriptorUtils.descriptorToJavaType(javaDescriptor);
          mapping.addMapping(javaType, featureJar.getOutputName());
        }
        try (ZipFile zipfile = new ZipFile(jarPath.toString(), StandardCharsets.UTF_8)) {
          Enumeration<? extends ZipEntry> entries = zipfile.entries();
          while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            String name = entry.getName();
            if (!ZipUtils.isClassFile(name)) {
              mapping.addNonClassMapping(name, featureJar.getOutputName());
            }
          }
        } catch (IOException e) {
          reporter.error(new ExceptionDiagnostic(e, new JarFileOrigin(jarPath)));
          throw new AbortException();
        }
      }
      assert mapping.usesOnlyExactMappings;
      return mapping;
    }

  }

  private FeatureClassMapping() {}

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