// Copyright (c) 2019, 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 com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.InterfaceMethodRewriter;
import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
import com.android.tools.r8.naming.FieldNameMinifier.FieldRenaming;
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.MethodNameMinifier.MethodRenaming;
import com.android.tools.r8.naming.Minifier.MinificationClassNamingStrategy;
import com.android.tools.r8.naming.Minifier.MinificationPackageNamingStrategy;
import com.android.tools.r8.naming.Minifier.MinifierMemberNamingStrategy;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * The ProguardMapMinifier will assign names to classes and members following the initial naming
 * seed given by the mapping files.
 *
 * <p>First the object hierarchy is traversed maintaining a collection of all program classes and
 * classes that needs to be renamed in {@link #mappedClasses}. For each level we keep track of all
 * renamed members and propagate all non-private items to descendants. This is necessary to ensure
 * that virtual methods are renamed when there are "gaps" in the hierarchy. We keep track of all
 * namings such that future renaming of non-private members will not collide or fail with an error.
 *
 * <p>Second, we compute desugared default interface methods and companion classes to ensure these
 * can be referred to by clients.
 *
 * <p>Third, we traverse all reachable interfaces for class mappings and add them to our tracking
 * maps. Otherwise, the minification follows the ordinary minification.
 */
public class ProguardMapMinifier {

  private final AppView<AppInfoWithLiveness> appView;
  private final SeedMapper seedMapper;
  private final Set<DexCallSite> desugaredCallSites;
  private final BiMap<DexType, DexString> mappedNames = HashBiMap.create();
  private final List<DexClass> mappedClasses = new ArrayList<>();
  private final Map<DexReference, MemberNaming> memberNames = new IdentityHashMap<>();
  private final Map<DexType, DexString> syntheticCompanionClasses = new IdentityHashMap<>();
  private final Map<DexMethod, DexString> defaultInterfaceMethodImplementationNames =
      new IdentityHashMap<>();
  private final Map<DexMethod, DexString> additionalMethodNamings = new IdentityHashMap<>();
  private final Map<DexField, DexString> additionalFieldNamings = new IdentityHashMap<>();

  public ProguardMapMinifier(
      AppView<AppInfoWithLiveness> appView,
      SeedMapper seedMapper,
      Set<DexCallSite> desugaredCallSites) {
    this.appView = appView;
    this.seedMapper = seedMapper;
    this.desugaredCallSites = desugaredCallSites;
  }

  public NamingLens run(Timing timing) {
    timing.begin("MappingClasses");
    computeMapping(appView.dexItemFactory().objectType, new ArrayDeque<>());
    timing.end();

    timing.begin("MappingDefaultInterfaceMethods");
    computeDefaultInterfaceMethodMethods();
    timing.end();

    timing.begin("ComputeInterfaces");
    // We have to compute interfaces
    Set<DexClass> interfaces = new TreeSet<>((a, b) -> a.type.slowCompareTo(b.type));
    for (DexClass dexClass : appView.appInfo().computeReachableInterfaces(desugaredCallSites)) {
      ClassNamingForMapApplier classNaming = seedMapper.getClassNaming(dexClass.type);
      if (classNaming != null) {
        DexString mappedName = appView.dexItemFactory().createString(classNaming.renamedName);
        checkAndAddMappedNames(dexClass.type, mappedName, classNaming.position);
      }
      mappedClasses.add(dexClass);
      interfaces.add(dexClass);
    }
    timing.end();

    appView.options().reporter.failIfPendingErrors();

    // To keep the order deterministic, we sort the classes by their type, which is a unique key.
    mappedClasses.sort((a, b) -> a.type.slowCompareTo(b.type));

    timing.begin("MinifyClasses");
    ClassNameMinifier classNameMinifier =
        new ClassNameMinifier(
            appView,
            new ApplyMappingClassNamingStrategy(appView, mappedNames),
            // The package naming strategy will actually not be used since all classes and methods
            // will be output with identity name if not found in mapping. However, there is a check
            // in the ClassNameMinifier that the strategy should produce a "fresh" name so we just
            // use the existing strategy.
            new MinificationPackageNamingStrategy(appView),
            mappedClasses);
    ClassRenaming classRenaming =
        classNameMinifier.computeRenaming(timing, syntheticCompanionClasses);
    timing.end();

    ApplyMappingMemberNamingStrategy nameStrategy =
        new ApplyMappingMemberNamingStrategy(appView, memberNames);
    timing.begin("MinifyMethods");
    MethodRenaming methodRenaming =
        new MethodNameMinifier(appView, nameStrategy)
            .computeRenaming(interfaces, desugaredCallSites, timing);
    // Amend the method renamings with the default interface methods.
    methodRenaming.renaming.putAll(defaultInterfaceMethodImplementationNames);
    methodRenaming.renaming.putAll(additionalMethodNamings);
    timing.end();

    timing.begin("MinifyFields");
    FieldRenaming fieldRenaming =
        new FieldNameMinifier(appView, nameStrategy).computeRenaming(interfaces, timing);
    fieldRenaming.renaming.putAll(additionalFieldNamings);
    timing.end();

    appView.options().reporter.failIfPendingErrors();

    NamingLens lens = new MinifiedRenaming(appView, classRenaming, methodRenaming, fieldRenaming);

    timing.begin("MinifyIdentifiers");
    new IdentifierMinifier(appView, lens).run();
    timing.end();

    return lens;
  }

  private void computeMapping(DexType type, Deque<Map<DexReference, MemberNaming>> buildUpNames) {
    ClassNamingForMapApplier classNaming = seedMapper.getClassNaming(type);
    DexClass dexClass = appView.definitionFor(type);

    // Keep track of classes that needs to get renamed.
    if (dexClass != null && (classNaming != null || dexClass.isProgramClass())) {
      mappedClasses.add(dexClass);
    }

    Map<DexReference, MemberNaming> nonPrivateMembers = new IdentityHashMap<>();

    if (classNaming != null) {
      // TODO(b/133091438) assert that !dexClass.isLibaryClass();
      DexString mappedName = appView.dexItemFactory().createString(classNaming.renamedName);
      checkAndAddMappedNames(type, mappedName, classNaming.position);

      classNaming.forAllMethodNaming(
          memberNaming -> {
            Signature signature = memberNaming.getOriginalSignature();
            assert !signature.isQualified();
            DexMethod originalMethod =
                ((MethodSignature) signature).toDexMethod(appView.dexItemFactory(), type);
            assert !memberNames.containsKey(originalMethod);
            memberNames.put(originalMethod, memberNaming);
            DexEncodedMethod encodedMethod = appView.definitionFor(originalMethod);
            if (encodedMethod == null || !encodedMethod.accessFlags.isPrivate()) {
              nonPrivateMembers.put(originalMethod, memberNaming);
            }
          });
      classNaming.forAllFieldNaming(
          memberNaming -> {
            Signature signature = memberNaming.getOriginalSignature();
            assert !signature.isQualified();
            DexField originalField =
                ((FieldSignature) signature).toDexField(appView.dexItemFactory(), type);
            assert !memberNames.containsKey(originalField);
            memberNames.put(originalField, memberNaming);
            DexEncodedField encodedField = appView.definitionFor(originalField);
            if (encodedField == null || !encodedField.accessFlags.isPrivate()) {
              nonPrivateMembers.put(originalField, memberNaming);
            }
          });
    } else {
      // We have to ensure we do not rename to an existing member, that cannot be renamed.
      if (dexClass == null || !appView.options().isMinifying()) {
        checkAndAddMappedNames(type, type.descriptor, Position.UNKNOWN);
      } else if (appView.options().isMinifying()
          && appView.rootSet().mayNotBeMinified(type, appView)) {
        checkAndAddMappedNames(type, type.descriptor, Position.UNKNOWN);
      }
    }

    for (Map<DexReference, MemberNaming> parentMembers : buildUpNames) {
      for (DexReference key : parentMembers.keySet()) {
        if (key.isDexMethod()) {
          DexMethod parentReference = key.asDexMethod();
          DexMethod parentReferenceOnCurrentType =
              appView
                  .dexItemFactory()
                  .createMethod(type, parentReference.proto, parentReference.name);
          addMemberNaming(
              key, parentReferenceOnCurrentType, parentMembers, additionalMethodNamings);
        } else {
          DexField parentReference = key.asDexField();
          DexField parentReferenceOnCurrentType =
              appView
                  .dexItemFactory()
                  .createField(type, parentReference.type, parentReference.name);
          addMemberNaming(key, parentReferenceOnCurrentType, parentMembers, additionalFieldNamings);
        }
      }
    }

    if (nonPrivateMembers.size() > 0) {
      buildUpNames.addLast(nonPrivateMembers);
      appView
          .appInfo()
          .forAllExtendsSubtypes(type, subType -> computeMapping(subType, buildUpNames));
      buildUpNames.removeLast();
    } else {
      appView
          .appInfo()
          .forAllExtendsSubtypes(type, subType -> computeMapping(subType, buildUpNames));
    }
  }

  private <T extends DexReference> void addMemberNaming(
      DexReference key,
      T member,
      Map<DexReference, MemberNaming> parentMembers,
      Map<T, DexString> additionalMemberNamings) {
    // We might have overridden a naming in the direct class namings above.
    if (!memberNames.containsKey(member)) {
      DexString renamedName =
          appView.dexItemFactory().createString(parentMembers.get(key).getRenamedName());
      memberNames.put(member, parentMembers.get(key));
      additionalMemberNamings.put(member, renamedName);
    }
  }

  private void checkAndAddMappedNames(DexType type, DexString mappedName, Position position) {
    if (mappedNames.inverse().containsKey(mappedName)) {
      appView
          .options()
          .reporter
          .error(
              ApplyMappingError.mapToExistingClass(
                  type.toString(), mappedName.toString(), position));
    } else {
      mappedNames.put(type, mappedName);
    }
  }

  private void computeDefaultInterfaceMethodMethods() {
    for (String key : seedMapper.getKeyset()) {
      ClassNamingForMapApplier classNaming = seedMapper.getMapping(key);
      DexType type =
          appView.dexItemFactory().lookupType(appView.dexItemFactory().createString(key));
      if (type == null) {
        // The map contains additional mapping of classes compared to what we have seen. This should
        // have no effect.
        continue;
      }
      DexClass dexClass = appView.definitionFor(type);
      if (dexClass == null) {
        computeDefaultInterfaceMethodMappingsForType(
            type,
            classNaming,
            syntheticCompanionClasses,
            defaultInterfaceMethodImplementationNames);
        continue;
      }
    }
  }

  private void computeDefaultInterfaceMethodMappingsForType(
      DexType type,
      ClassNamingForMapApplier classNaming,
      Map<DexType, DexString> syntheticCompanionClasses,
      Map<DexMethod, DexString> defaultInterfaceMethodImplementationNames) {
    // If the class does not resolve, then check if it is a companion class for an interface on
    // the class path.
    if (!InterfaceMethodRewriter.isCompanionClassType(type)) {
      return;
    }
    DexClass interfaceType =
        appView.definitionFor(
            InterfaceMethodRewriter.getInterfaceClassType(type, appView.dexItemFactory()));
    if (interfaceType == null || !interfaceType.isClasspathClass()) {
      return;
    }
    syntheticCompanionClasses.put(
        type, appView.dexItemFactory().createString(classNaming.renamedName));
    for (List<MemberNaming> namings : classNaming.getQualifiedMethodMembers().values()) {
      // If the qualified name has been mapped to multiple names we can't compute a mapping (and it
      // should not be possible that this is a default interface method in that case.)
      if (namings.size() != 1) {
        continue;
      }
      MemberNaming naming = namings.get(0);
      MethodSignature signature = (MethodSignature) naming.getOriginalSignature();
      if (signature.name.startsWith(interfaceType.type.toSourceString())) {
        DexMethod defaultMethod =
            InterfaceMethodRewriter.defaultAsMethodOfCompanionClass(
                signature.toUnqualified().toDexMethod(appView.dexItemFactory(), interfaceType.type),
                appView.dexItemFactory());
        assert defaultMethod.holder == type;
        defaultInterfaceMethodImplementationNames.put(
            defaultMethod, appView.dexItemFactory().createString(naming.getRenamedName()));
      }
    }
  }

  static class ApplyMappingClassNamingStrategy extends MinificationClassNamingStrategy {

    private final Map<DexType, DexString> mappings;
    private final boolean isMinifying;

    ApplyMappingClassNamingStrategy(AppView<?> appView, Map<DexType, DexString> mappings) {
      super(appView);
      this.mappings = mappings;
      this.isMinifying = appView.options().isMinifying();
    }

    @Override
    public DexString next(DexType type, char[] packagePrefix, InternalNamingState state) {
      DexString nextName = mappings.get(type);
      if (nextName != null) {
        return nextName;
      }
      assert !(isMinifying && noObfuscation(type));
      return isMinifying ? super.next(type, packagePrefix, state) : type.descriptor;
    }

    @Override
    public boolean noObfuscation(DexType type) {
      if (mappings.containsKey(type)) {
        return false;
      }
      DexClass dexClass = appView.definitionFor(type);
      if (dexClass == null || dexClass.isNotProgramClass()) {
        return true;
      }
      return super.noObfuscation(type);
    }
  }

  static class ApplyMappingMemberNamingStrategy extends MinifierMemberNamingStrategy {

    private final Map<DexReference, MemberNaming> mappedNames;
    private final DexItemFactory factory;
    private final Reporter reporter;

    public ApplyMappingMemberNamingStrategy(
        AppView<?> appView, Map<DexReference, MemberNaming> mappedNames) {
      super(appView);
      this.mappedNames = mappedNames;
      this.factory = appView.dexItemFactory();
      this.reporter = appView.options().reporter;
    }

    @Override
    public DexString next(DexMethod method, InternalNamingState internalState) {
      assert !mappedNames.containsKey(method);
      return canMinify(method, method.holder) ? super.next(method, internalState) : method.name;
    }

    @Override
    public DexString next(DexField field, InternalNamingState internalState) {
      assert !mappedNames.containsKey(field);
      return canMinify(field, field.holder) ? super.next(field, internalState) : field.name;
    }

    private boolean canMinify(DexReference reference, DexType type) {
      if (!appView.options().isMinifying()) {
        return false;
      }
      DexClass dexClass = appView.definitionFor(type);
      if (dexClass == null || dexClass.isNotProgramClass()) {
        return false;
      }
      return appView.rootSet().mayBeMinified(reference, appView);
    }

    @Override
    public DexString getReservedNameOrDefault(
        DexEncodedMethod method, DexClass holder, DexString nullValue) {
      if (mappedNames.containsKey(method.method)) {
        return factory.createString(mappedNames.get(method.method).getRenamedName());
      }
      return nullValue;
    }

    @Override
    public DexString getReservedNameOrDefault(
        DexEncodedField field, DexClass holder, DexString nullValue) {
      if (mappedNames.containsKey(field.field)) {
        return factory.createString(mappedNames.get(field.field).getRenamedName());
      }
      return nullValue;
    }

    @Override
    public boolean allowMemberRenaming(DexClass holder) {
      return true;
    }

    @Override
    public void reportReservationError(DexReference source, DexString name) {
      MemberNaming memberNaming = mappedNames.get(source);
      assert source.isDexMethod() || source.isDexField();
      ApplyMappingError applyMappingError =
          ApplyMappingError.mapToExistingMember(
              source.toSourceString(),
              name.toString(),
              memberNaming == null ? Position.UNKNOWN : memberNaming.position);
      reporter.error(applyMappingError);
    }
  }
}
