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

import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.collect.Iterables;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class VirtualMethodMerger {

  private final AppView<? extends AppInfoWithClassHierarchy> appView;
  private final DexItemFactory dexItemFactory;
  private final MergeGroup group;
  private final List<ProgramMethod> methods;
  private final DexMethod superMethod;

  public VirtualMethodMerger(
      AppView<? extends AppInfoWithClassHierarchy> appView,
      MergeGroup group,
      List<ProgramMethod> methods,
      DexMethod superMethod) {
    this.appView = appView;
    this.dexItemFactory = appView.dexItemFactory();
    this.group = group;
    this.methods = methods;
    this.superMethod = superMethod;
  }

  public static class Builder {
    private final List<ProgramMethod> methods = new ArrayList<>();

    public Builder add(ProgramMethod method) {
      methods.add(method);
      return this;
    }

    /** Get the super method handle if this method overrides a parent method. */
    private DexMethod superMethod(
        AppView<? extends AppInfoWithClassHierarchy> appView, MergeGroup group) {
      DexMethod template = methods.iterator().next().getReference();
      SingleResolutionResult resolutionResult =
          appView
              .appInfo()
              .resolveMethodOnClass(template, group.getSuperType())
              .asSingleResolution();
      if (resolutionResult == null || resolutionResult.getResolvedMethod().isAbstract()) {
        // If there is no super method or the method is abstract it should not be called.
        return null;
      }
      if (resolutionResult.getResolvedHolder().isInterface()) {
        // Ensure that invoke virtual isn't called on an interface method.
        return resolutionResult
            .getResolvedMethod()
            .getReference()
            .withHolder(group.getSuperType(), appView.dexItemFactory());
      }
      return resolutionResult.getResolvedMethod().getReference();
    }

    public VirtualMethodMerger build(
        AppView<? extends AppInfoWithClassHierarchy> appView, MergeGroup group) {
      // If not all the classes are in the merge group, find the fallback super method to call.
      DexMethod superMethod = methods.size() < group.size() ? superMethod(appView, group) : null;
      return new VirtualMethodMerger(appView, group, methods, superMethod);
    }
  }

  public DexMethod getMethodReference() {
    return methods.iterator().next().getReference();
  }

  public int getArity() {
    return getMethodReference().getArity();
  }

  private DexMethod moveMethod(ClassMethodsBuilder classMethodsBuilder, ProgramMethod oldMethod) {
    DexMethod oldMethodReference = oldMethod.getReference();
    DexMethod method =
        dexItemFactory.createFreshMethodNameWithHolder(
            oldMethodReference.name.toSourceString(),
            oldMethod.getHolderType(),
            oldMethodReference.proto,
            group.getTarget().getType(),
            classMethodsBuilder::isFresh);

    DexEncodedMethod encodedMethod = oldMethod.getDefinition().toTypeSubstitutedMethod(method);
    MethodAccessFlags flags = encodedMethod.getAccessFlags();
    flags.unsetProtected();
    flags.unsetPublic();
    flags.setPrivate();
    classMethodsBuilder.addDirectMethod(encodedMethod);

    return encodedMethod.getReference();
  }

  private MethodAccessFlags getAccessFlags() {
    Iterable<MethodAccessFlags> allFlags =
        Iterables.transform(methods, ProgramMethod::getAccessFlags);
    MethodAccessFlags result = allFlags.iterator().next().copy();
    assert Iterables.all(allFlags, flags -> !flags.isNative());
    assert !result.isStrict() || Iterables.all(allFlags, MethodAccessFlags::isStrict);
    assert !result.isSynchronized() || Iterables.all(allFlags, MethodAccessFlags::isSynchronized);
    if (result.isAbstract() && Iterables.any(allFlags, flags -> !flags.isAbstract())) {
      result.unsetAbstract();
    }
    if (result.isBridge() && Iterables.any(allFlags, flags -> !flags.isBridge())) {
      result.unsetBridge();
    }
    if (result.isFinal()) {
      if (methods.size() < group.size() || Iterables.any(allFlags, flags -> !flags.isFinal())) {
        result.unsetFinal();
      }
    }
    if (result.isSynthetic() && Iterables.any(allFlags, flags -> !flags.isSynthetic())) {
      result.unsetSynthetic();
    }
    if (result.isVarargs() && Iterables.any(allFlags, flags -> !flags.isVarargs())) {
      result.unsetVarargs();
    }
    result.unsetDeclaredSynchronized();
    return result;
  }

  private DexMethod getNewMethodReference() {
    return ListUtils.first(methods).getReference().withHolder(group.getTarget(), dexItemFactory);
  }

  /**
   * If there is a super method and all methods are abstract, then we can simply remove all abstract
   * methods.
   */
  private boolean isNop() {
    return superMethod != null
        && Iterables.all(methods, method -> method.getDefinition().isAbstract());
  }

  /**
   * If the method is present on all classes in the merge group, and there is at most one
   * non-abstract method, then we can simply move that method (or the first abstract method) to the
   * target class.
   */
  private boolean isTrivial() {
    if (superMethod != null) {
      return false;
    }
    if (methods.size() == 1) {
      return true;
    }
    int numberOfNonAbstractMethods =
        Iterables.size(Iterables.filter(methods, method -> !method.getDefinition().isAbstract()));
    return numberOfNonAbstractMethods <= 1;
  }

  boolean isNopOrTrivial() {
    return isNop() || isTrivial();
  }

  /**
   * If there is only a single method that does not override anything then it is safe to just move
   * it to the target type if it is not already in it.
   */
  private void mergeTrivial(
      ClassMethodsBuilder classMethodsBuilder, HorizontalClassMergerGraphLens.Builder lensBuilder) {
    DexMethod newMethodReference = getNewMethodReference();

    // Find the first non-abstract method. If all are abstract, then select the first method.
    ProgramMethod representative =
        Iterables.find(methods, method -> !method.getDefinition().isAbstract(), null);
    if (representative == null) {
      representative = ListUtils.first(methods);
    }

    if (representative.getAccessFlags().isAbstract() && superMethod != null) {
      methods.forEach(method -> lensBuilder.mapMethod(method.getReference(), newMethodReference));
      return;
    }

    for (ProgramMethod method : methods) {
      if (method.getReference() == representative.getReference()) {
        lensBuilder.moveMethod(method.getReference(), newMethodReference);
      } else {
        lensBuilder.mapMethod(method.getReference(), newMethodReference);
      }
    }

    DexEncodedMethod newMethod;
    if (representative.getHolder() == group.getTarget()) {
      newMethod = representative.getDefinition();
    } else {
      // If the method is not in the target type, move it.
      OptionalBool isLibraryMethodOverride =
          representative.getDefinition().isLibraryMethodOverride();
      newMethod =
          representative
              .getDefinition()
              .toTypeSubstitutedMethod(
                  newMethodReference,
                  builder -> builder.setIsLibraryMethodOverrideIfKnown(isLibraryMethodOverride));
    }

    newMethod.getAccessFlags().unsetFinal();

    classMethodsBuilder.addVirtualMethod(newMethod);
  }

  public void merge(
      ClassMethodsBuilder classMethodsBuilder,
      HorizontalClassMergerGraphLens.Builder lensBuilder,
      Reference2IntMap<DexType> classIdentifiers,
      Consumer<VirtuallyMergedMethodsKeepInfo> virtuallyMergedMethodsKeepInfoConsumer) {
    assert !methods.isEmpty();

    // Handle trivial merges.
    if (isNopOrTrivial()) {
      mergeTrivial(classMethodsBuilder, lensBuilder);
      return;
    }

    Int2ReferenceSortedMap<DexMethod> classIdToMethodMap = new Int2ReferenceAVLTreeMap<>();

    CfVersion classFileVersion = null;
    ProgramMethod representative = null;
    for (ProgramMethod method : methods) {
      if (method.getDefinition().isAbstract()) {
        continue;
      }
      if (method.getDefinition().hasClassFileVersion()) {
        CfVersion methodVersion = method.getDefinition().getClassFileVersion();
        classFileVersion = Ordered.maxIgnoreNull(classFileVersion, methodVersion);
      }
      DexMethod newMethod = moveMethod(classMethodsBuilder, method);
      lensBuilder.recordNewMethodSignature(method.getReference(), newMethod);
      classIdToMethodMap.put(
          classIdentifiers.getInt(method.getHolderType()), method.getReference());
      if (representative == null) {
        representative = method;
      }
    }

    assert representative != null;

    // Use the first of the original methods as the original method for the merged constructor.
    DexMethod originalMethodReference =
        appView.graphLens().getOriginalMethodSignature(representative.getReference());
    DexMethod bridgeMethodReference =
        dexItemFactory.createFreshMethodNameWithoutHolder(
            originalMethodReference.getName().toSourceString() + "$bridge",
            originalMethodReference.proto,
            originalMethodReference.getHolderType(),
            classMethodsBuilder::isFresh);
    DexEncodedMethod representativeMethod = representative.getDefinition();
    DexMethod newMethodReference = getNewMethodReference();
    IncompleteVirtuallyMergedMethodCode synthesizedCode =
        new IncompleteVirtuallyMergedMethodCode(
            group.getClassIdField(), classIdToMethodMap, originalMethodReference, superMethod);
    DexEncodedMethod newMethod =
        DexEncodedMethod.syntheticBuilder()
            .setMethod(newMethodReference)
            .setAccessFlags(getAccessFlags())
            .setCode(synthesizedCode)
            .setClassFileVersion(classFileVersion)
            .setApiLevelForDefinition(representativeMethod.getApiLevelForDefinition())
            .setApiLevelForCode(representativeMethod.getApiLevelForCode())
            .build();
    if (!representative.getDefinition().isLibraryMethodOverride().isUnknown()) {
      newMethod.setLibraryMethodOverride(representative.getDefinition().isLibraryMethodOverride());
    }

    // Map each old non-abstract method to the newly synthesized method in the graph lens.
    VirtuallyMergedMethodsKeepInfo virtuallyMergedMethodsKeepInfo =
        new VirtuallyMergedMethodsKeepInfo(representative.getReference());
    for (ProgramMethod oldMethod : methods) {
      lensBuilder.mapMethod(oldMethod.getReference(), newMethodReference);
      virtuallyMergedMethodsKeepInfo.amendKeepInfo(appView.getKeepInfo(oldMethod));
    }

    // The super method reference is not guaranteed to be rebound to a definition. To ensure correct
    // lens code rewriting we need to disable proto normalization until lens code rewriting no
    // longer relies on member rebinding (b/182129249).
    if (superMethod != null) {
      virtuallyMergedMethodsKeepInfo.getKeepInfo().disallowParameterReordering();
    }

    // Add a mapping from a synthetic name to the synthetic merged method.
    lensBuilder.recordNewMethodSignature(bridgeMethodReference, newMethodReference);

    classMethodsBuilder.addVirtualMethod(newMethod);

    if (!virtuallyMergedMethodsKeepInfo.getKeepInfo().isBottom()) {
      virtuallyMergedMethodsKeepInfoConsumer.accept(virtuallyMergedMethodsKeepInfo);
    }
  }
}
