// 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.dexsplitter.DexSplitter.FeatureJar;
import java.io.IOException;
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.regex.Pattern;

/**
 * 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.
 */
public class FeatureClassMapping {

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

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

  Path mappingFile;
  String baseName;

  static final String DEFAULT_BASE_NAME = "base";

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


  public static FeatureClassMapping fromSpecification(Path file)
      throws FeatureMappingException, IOException {
    FeatureClassMapping mapping = new FeatureClassMapping();
    mapping.baseName = DEFAULT_BASE_NAME;
    List<String> lines = FileUtils.readAllLines(file);
    for (int i = 0; i < lines.size(); i++) {
      String line = lines.get(i);
      mapping.parseAndAdd(line, i);
    }
    return mapping;
  }

  public static FeatureClassMapping fromJarFiles(List<FeatureJar> featureJars, String baseName)
      throws FeatureMappingException, IOException {
    FeatureClassMapping mapping = new FeatureClassMapping();
    mapping.baseName = baseName != null ? baseName : DEFAULT_BASE_NAME;
    for (FeatureJar featureJar : featureJars) {
      Path jarPath = Paths.get(featureJar.getJar());
      ArchiveClassFileProvider provider = new ArchiveClassFileProvider(jarPath);
      for (String javaDescriptor : provider.getClassDescriptors()) {
          String javaType = DescriptorUtils.descriptorToJavaType(javaDescriptor);
          mapping.addMapping(javaType, featureJar.getOutputName());
      }
    }
    return mapping;
  }

  private FeatureClassMapping() {}

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

  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) throws FeatureMappingException {
    // Todo(ricow): improve performance (e.g., direct lookup of class predicates through hashmap).
    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;
  }

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

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

  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) {
        this.predicate = predicate.substring(0, predicate.length() - 2);
      } else {
        this.predicate = predicate;
      }
      if (!DescriptorUtils.isValidJavaType(this.predicate) && !isCatchAll) {
        throw new FeatureMappingException(this.predicate + " is not a valid identifier");
      }
      this.feature = feature;
    }

    boolean match(String className) {
      if (isCatchAll) {
        return true;
      } else if (isWildcard) {
        return className.startsWith(predicate);
      } else {
        // We also put inner classes into the same feature.
        return className.startsWith(predicate);
      }
    }
  }
}
