// Copyright (c) 2016, 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.naming;

import static com.android.tools.r8.naming.ClassNameMapper.MissingFileAction.MISSING_FILE_IS_ERROR;
import static com.android.tools.r8.utils.DescriptorUtils.descriptorToJavaType;

import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
import com.android.tools.r8.naming.mappinginformation.MapVersionMappingInformation;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.utils.BiMapContainer;
import com.android.tools.r8.utils.ChainableStringConsumer;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Reporter;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.CharSource;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;

public class ClassNameMapper implements ProguardMap {

  public enum MissingFileAction {
    MISSING_FILE_IS_EMPTY_MAP,
    MISSING_FILE_IS_ERROR
  }

  public static class Builder extends ProguardMap.Builder {

    private boolean buildPreamble = false;
    private boolean addVersionAsPreamble = false;
    private final List<String> preamble = new ArrayList<>();
    private final Map<String, ClassNamingForNameMapper.Builder> mapping = new HashMap<>();
    private final LinkedHashSet<MapVersionMappingInformation> mapVersions = new LinkedHashSet<>();
    private final Map<String, String> originalSourceFiles = new HashMap<>();

    @Override
    public ClassNamingForNameMapper.Builder classNamingBuilder(
        String renamedName, String originalName, Position position) {
      ClassNamingForNameMapper.Builder classNamingBuilder =
          ClassNamingForNameMapper.builder(renamedName, originalName, originalSourceFiles::put);
      mapping.put(renamedName, classNamingBuilder);
      return classNamingBuilder;
    }

    public Builder setBuildPreamble(boolean buildPreamble) {
      this.buildPreamble = buildPreamble;
      return this;
    }

    public Builder setAddVersionAsPreamble(boolean addVersionAsPreamble) {
      this.addVersionAsPreamble = addVersionAsPreamble;
      return this;
    }

    @Override
    public void addPreambleLine(String line) {
      if (buildPreamble) {
        preamble.add(line);
      }
    }

    public boolean hasMapping(String obfuscatedName) {
      return mapping.containsKey(obfuscatedName);
    }

    @Override
    public ClassNameMapper build() {
      return new ClassNameMapper(
          buildClassNameMappings(), mapVersions, originalSourceFiles, preamble);
    }

    private ImmutableMap<String, ClassNamingForNameMapper> buildClassNameMappings() {
      ImmutableMap.Builder<String, ClassNamingForNameMapper> builder = ImmutableMap.builder();
      mapping.forEach(
          (renamedName, valueBuilder) -> builder.put(renamedName, valueBuilder.build()));
      return builder.build();
    }

    @Override
    public ProguardMap.Builder setCurrentMapVersion(MapVersionMappingInformation mapVersion) {
      mapVersions.add(mapVersion);
      if (addVersionAsPreamble) {
        addPreambleLine("# " + mapVersion.serialize());
      }
      return this;
    }

    @Override
    ProguardMap.Builder addFileName(String originalName, String fileName) {
      originalSourceFiles.put(originalName, fileName);
      return this;
    }
  }

  public static Builder builder() {
    return new Builder();
  }

  public static ClassNameMapper mapperFromFile(Path path) throws IOException {
    return mapperFromFile(path, MISSING_FILE_IS_ERROR);
  }

  public static ClassNameMapper mapperFromFile(Path path, MissingFileAction missingFileAction)
      throws IOException {
    assert missingFileAction == MissingFileAction.MISSING_FILE_IS_EMPTY_MAP
        || missingFileAction == MISSING_FILE_IS_ERROR;
    if (missingFileAction == MissingFileAction.MISSING_FILE_IS_EMPTY_MAP
        && !path.toFile().exists()) {
      return mapperFromString("");
    }
    return mapperFromBufferedReader(Files.newBufferedReader(path, StandardCharsets.UTF_8), null);
  }

  public static ClassNameMapper mapperFromString(String contents) throws IOException {
    return mapperFromBufferedReader(CharSource.wrap(contents).openBufferedStream(), null);
  }

  public static ClassNameMapper mapperFromStringWithPreamble(String contents) throws IOException {
    return mapperFromBufferedReader(
        CharSource.wrap(contents).openBufferedStream(), null, false, false, true);
  }

  public static ClassNameMapper mapperFromFileWithPreamble(
      Path path, MissingFileAction missingFileAction) throws Exception {
    assert missingFileAction == MissingFileAction.MISSING_FILE_IS_EMPTY_MAP
        || missingFileAction == MISSING_FILE_IS_ERROR;
    if (missingFileAction == MissingFileAction.MISSING_FILE_IS_EMPTY_MAP
        && !path.toFile().exists()) {
      return mapperFromString("");
    }
    return mapperFromBufferedReader(
        Files.newBufferedReader(path, StandardCharsets.UTF_8), null, false, false, true);
  }

  public static ClassNameMapper mapperFromString(
      String contents, DiagnosticsHandler diagnosticsHandler) throws IOException {
    return mapperFromBufferedReader(
        CharSource.wrap(contents).openBufferedStream(), diagnosticsHandler);
  }

  public static ClassNameMapper mapperFromString(
      String contents,
      DiagnosticsHandler diagnosticsHandler,
      boolean allowEmptyMappedRanges,
      boolean allowExperimentalMapping,
      boolean buildPreamble)
      throws IOException {
    return mapperFromLineReaderWithFiltering(
        LineReader.fromBufferedReader(CharSource.wrap(contents).openBufferedStream()),
        MapVersion.MAP_VERSION_NONE,
        diagnosticsHandler,
        allowEmptyMappedRanges,
        allowExperimentalMapping,
        builder -> builder.setBuildPreamble(buildPreamble));
  }

  private static ClassNameMapper mapperFromBufferedReader(
      BufferedReader reader, DiagnosticsHandler diagnosticsHandler) throws IOException {
    return mapperFromBufferedReader(reader, diagnosticsHandler, false, false, false);
  }

  public static ClassNameMapper mapperFromBufferedReader(
      BufferedReader reader,
      DiagnosticsHandler diagnosticsHandler,
      boolean allowEmptyMappedRanges,
      boolean allowExperimentalMapping,
      boolean buildPreamble)
      throws IOException {
    return mapperFromLineReaderWithFiltering(
        LineReader.fromBufferedReader(reader),
        MapVersion.MAP_VERSION_NONE,
        diagnosticsHandler,
        allowEmptyMappedRanges,
        allowExperimentalMapping,
        builder -> builder.setBuildPreamble(buildPreamble));
  }

  public static ClassNameMapper mapperFromLineReaderWithFiltering(
      LineReader reader,
      MapVersion mapVersion,
      DiagnosticsHandler diagnosticsHandler,
      boolean allowEmptyMappedRanges,
      boolean allowExperimentalMapping,
      Consumer<ClassNameMapper.Builder> builderConsumer)
      throws IOException {
    try (ProguardMapReader proguardReader =
        new ProguardMapReader(
            reader,
            diagnosticsHandler != null ? diagnosticsHandler : new Reporter(),
            allowEmptyMappedRanges,
            allowExperimentalMapping,
            mapVersion)) {
      ClassNameMapper.Builder builder = ClassNameMapper.builder();
      builderConsumer.accept(builder);
      proguardReader.parse(builder);
      return builder.build();
    }
  }

  private final ImmutableMap<String, ClassNamingForNameMapper> classNameMappings;
  private BiMapContainer<String, String> nameMapping;
  private final Map<Signature, Signature> signatureMap = new ConcurrentHashMap<>();
  private final LinkedHashSet<MapVersionMappingInformation> mapVersions;
  private final Map<String, String> originalSourceFiles;
  private List<String> preamble;

  private ClassNameMapper(
      ImmutableMap<String, ClassNamingForNameMapper> classNameMappings,
      LinkedHashSet<MapVersionMappingInformation> mapVersions,
      Map<String, String> originalSourceFiles,
      List<String> preamble) {
    this.classNameMappings = classNameMappings;
    this.mapVersions = mapVersions;
    this.originalSourceFiles = originalSourceFiles;
    this.preamble = preamble;
  }

  public Map<String, ClassNamingForNameMapper> getClassNameMappings() {
    return classNameMappings;
  }

  public List<String> getPreamble() {
    return preamble;
  }

  public Set<String> getObfuscatedPackages() {
    Set<String> packages = new HashSet<>();
    classNameMappings.forEach(
        (s, classNamingForNameMapper) ->
            packages.add(DescriptorUtils.getPackageNameFromTypeName(s)));
    return packages;
  }

  public void setPreamble(List<String> preamble) {
    this.preamble = preamble;
  }

  private Signature canonicalizeSignature(Signature signature) {
    Signature result = signatureMap.get(signature);
    if (result != null) {
      return result;
    }
    signatureMap.put(signature, signature);
    return signature;
  }

  public MethodSignature getRenamedMethodSignature(DexMethod method) {
    DexType[] parameters = method.proto.parameters.values;
    String[] parameterTypes = new String[parameters.length];
    for (int i = 0; i < parameters.length; i++) {
      parameterTypes[i] = deobfuscateType(parameters[i].toDescriptorString());
    }
    String returnType = deobfuscateType(method.proto.returnType.toDescriptorString());

    MethodSignature signature = new MethodSignature(method.name.toString(), returnType,
        parameterTypes);
    return (MethodSignature) canonicalizeSignature(signature);
  }

  public FieldSignature getRenamedFieldSignature(DexField field) {
    String type = deobfuscateType(field.type.toDescriptorString());
    return (FieldSignature) canonicalizeSignature(new FieldSignature(field.name.toString(), type));
  }

  /**
   * Deobfuscate a class name.
   *
   * <p>Returns the deobfuscated name if a mapping was found. Otherwise it returns the passed in
   * name.
   */
  public String deobfuscateClassName(String obfuscatedName) {
    ClassNamingForNameMapper classNaming = classNameMappings.get(obfuscatedName);
    if (classNaming == null) {
      return obfuscatedName;
    }
    return classNaming.originalName;
  }

  private String deobfuscateType(String asString) {
    return descriptorToJavaType(asString, this);
  }

  public String getSourceFile(String typeName) {
    return originalSourceFiles.get(typeName);
  }

  public ClassNameMapper combine(ClassNameMapper other) {
    if (other == null || other.isEmpty()) {
      return this;
    }
    if (this.isEmpty()) {
      return other;
    }
    ImmutableMap.Builder<String, ClassNamingForNameMapper> builder = ImmutableMap.builder();
    Map<String, ClassNamingForNameMapper> otherClassMappings = other.getClassNameMappings();
    for (Entry<String, ClassNamingForNameMapper> mappingEntry : classNameMappings.entrySet()) {
      ClassNamingForNameMapper otherMapping = otherClassMappings.get(mappingEntry.getKey());
      if (otherMapping == null) {
        builder.put(mappingEntry);
      } else {
        builder.put(mappingEntry.getKey(), mappingEntry.getValue().combine(otherMapping));
      }
    }
    otherClassMappings.forEach(
        (otherMappingClass, otherMapping) -> {
          // Collisions are handled above so only take non-existing mappings.
          if (!classNameMappings.containsKey(otherMappingClass)) {
            builder.put(otherMappingClass, otherMapping);
          }
        });
    LinkedHashSet<MapVersionMappingInformation> newMapVersions =
        new LinkedHashSet<>(getMapVersions());
    newMapVersions.addAll(other.getMapVersions());
    Map<String, String> newSourcesFiles = new HashMap<>(originalSourceFiles);
    // This will overwrite existing source files but the chance of that happening should be very
    // slim.
    newSourcesFiles.putAll(other.originalSourceFiles);

    List<String> newPreamble = Collections.emptyList();
    if (!this.preamble.isEmpty() || !other.preamble.isEmpty()) {
      newPreamble = new ArrayList<>();
      newPreamble.addAll(this.preamble);
      newPreamble.addAll(other.preamble);
    }
    return new ClassNameMapper(builder.build(), newMapVersions, newSourcesFiles, newPreamble);
  }

  @Override
  public boolean hasMapping(DexType type) {
    String decoded = descriptorToJavaType(type.descriptor.toString());
    return classNameMappings.containsKey(decoded);
  }

  @Override
  public ClassNamingForNameMapper getClassNaming(DexType type) {
    String decoded = descriptorToJavaType(type.descriptor.toString());
    return classNameMappings.get(decoded);
  }

  public ClassNamingForNameMapper getClassNaming(String obfuscatedName) {
    return classNameMappings.get(obfuscatedName);
  }

  public boolean isEmpty() {
    return classNameMappings.isEmpty() && preamble.isEmpty();
  }

  public ClassNameMapper sorted() {
    ImmutableMap.Builder<String, ClassNamingForNameMapper> builder = ImmutableMap.builder();
    builder.orderEntriesByValue(Comparator.comparing(x -> x.originalName));
    classNameMappings.forEach(builder::put);
    return new ClassNameMapper(builder.build(), mapVersions, originalSourceFiles, preamble);
  }

  public boolean verifyIsSorted() {
    Iterator<Entry<String, ClassNamingForNameMapper>> iterator =
        getClassNameMappings().entrySet().iterator();
    Iterator<Entry<String, ClassNamingForNameMapper>> sortedIterator =
        sorted().getClassNameMappings().entrySet().iterator();
    while (iterator.hasNext()) {
      Entry<String, ClassNamingForNameMapper> entry = iterator.next();
      Entry<String, ClassNamingForNameMapper> otherEntry = sortedIterator.next();
      assert entry.getKey().equals(otherEntry.getKey());
      assert entry.getValue() == otherEntry.getValue();
    }
    return true;
  }

  public void write(ChainableStringConsumer consumer) {
    // Classes should be sorted by their original name such that the generated Proguard map is
    // deterministic (and easy to navigate manually).
    assert verifyIsSorted();
    for (ClassNamingForNameMapper naming : getClassNameMappings().values()) {
      naming.write(consumer);
    }
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    write(ChainableStringConsumer.wrap(builder::append));
    return builder.toString();
  }

  public BiMapContainer<String, String> getObfuscatedToOriginalMapping() {
    if (nameMapping == null) {
      ImmutableBiMap.Builder<String, String> builder = ImmutableBiMap.builder();
      for (String name : classNameMappings.keySet()) {
        builder.put(name, classNameMappings.get(name).originalName);
      }
      BiMap<String, String> classNameMappings = builder.build();
      nameMapping = new BiMapContainer<>(classNameMappings, classNameMappings.inverse());
    }
    return nameMapping;
  }

  @Override
  public boolean equals(Object o) {
    return o instanceof ClassNameMapper
        && classNameMappings.equals(((ClassNameMapper) o).classNameMappings);
  }

  @Override
  public int hashCode() {
    return 31 * classNameMappings.hashCode();
  }

  public String originalNameOf(IndexedDexItem item) {
    if (item instanceof DexField) {
      return lookupName(getRenamedFieldSignature((DexField) item), ((DexField) item).holder);
    } else if (item instanceof DexMethod) {
      return lookupName(getRenamedMethodSignature((DexMethod) item), ((DexMethod) item).holder);
    } else if (item instanceof DexType) {
      return descriptorToJavaType(((DexType) item).toDescriptorString(), this);
    } else {
      return item.toString();
    }
  }

  private String lookupName(Signature signature, DexType clazz) {
    String decoded = descriptorToJavaType(clazz.descriptor.toString());
    ClassNamingForNameMapper classNaming = getClassNaming(decoded);
    if (classNaming == null) {
      return decoded + " " + signature.toString();
    }
    MemberNaming memberNaming = classNaming.lookup(signature);
    if (memberNaming == null) {
      return classNaming.originalName + " " + signature;
    }
    return classNaming.originalName + " " + memberNaming.getOriginalSignature().toString();
  }

  public MethodSignature originalSignatureOf(DexMethod method) {
    String decoded = descriptorToJavaType(method.holder.descriptor.toString());
    MethodSignature memberSignature = getRenamedMethodSignature(method);
    ClassNaming classNaming = getClassNaming(decoded);
    if (classNaming == null) {
      return memberSignature;
    }
    MemberNaming memberNaming = classNaming.lookup(memberSignature);
    if (memberNaming == null) {
      return memberSignature;
    }
    return memberNaming.getOriginalSignature().asMethodSignature();
  }

  public FieldSignature originalSignatureOf(DexField field) {
    String decoded = descriptorToJavaType(field.holder.descriptor.toString());
    FieldSignature memberSignature = getRenamedFieldSignature(field);
    ClassNaming classNaming = getClassNaming(decoded);
    if (classNaming == null) {
      return memberSignature;
    }
    MemberNaming memberNaming = classNaming.lookup(memberSignature);
    if (memberNaming == null) {
      return memberSignature;
    }
    return memberNaming.getOriginalSignature().asFieldSignature();
  }

  public String originalNameOf(DexType clazz) {
    return deobfuscateType(clazz.descriptor.toString());
  }

  public Set<MapVersionMappingInformation> getMapVersions() {
    return mapVersions;
  }

  public MapVersionMappingInformation getFirstMapVersionInformation() {
    return mapVersions.isEmpty() ? null : mapVersions.iterator().next();
  }
}
