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

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