// Copyright (c) 2021, 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.ir.desugar.desugaredlibrary.retargeter;

import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.ClasspathMethod;
import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
import com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeterSynthesizerEventConsumer.DesugaredLibraryRetargeterInstructionEventConsumer;
import com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeterSynthesizerEventConsumer.DesugaredLibraryRetargeterL8SynthesizerEventConsumer;
import com.android.tools.r8.ir.synthetic.EmulateDispatchSyntheticCfCodeProvider;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
import com.android.tools.r8.synthesis.SyntheticClassBuilder;
import com.android.tools.r8.synthesis.SyntheticItems.SyntheticKindSelector;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import java.util.LinkedHashMap;

public class DesugaredLibraryRetargeterSyntheticHelper {

  private final AppView<?> appView;

  public DesugaredLibraryRetargeterSyntheticHelper(AppView<?> appView) {
    this.appView = appView;
  }

  public DexMethod ensureCovariantRetargetMethod(
      DexMethod target,
      DexMethod retarget,
      DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer,
      MethodProcessingContext methodProcessingContext) {
    ProgramMethod method =
        appView
            .getSyntheticItems()
            .createMethod(
                kinds -> kinds.COVARIANT_OUTLINE,
                methodProcessingContext.createUniqueContext(),
                appView,
                methodBuilder ->
                    methodBuilder
                        .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
                        .setProto(appView.dexItemFactory().prependHolderToProto(target))
                        .setCode(
                            m ->
                                ForwardMethodBuilder.builder(appView.dexItemFactory())
                                    .setVirtualTarget(retarget, false)
                                    .setNonStaticSource(target)
                                    .setCastResult()
                                    .build()));
    eventConsumer.acceptCovariantRetargetMethod(method);
    return method.getReference();
  }

  public DexMethod ensureRetargetMethod(
      DexMethod retarget, DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer) {
    DexClass holderClass = appView.definitionFor(retarget.getHolderType());
    if (holderClass != null && !holderClass.isClasspathClass()) {
      // The holder class is a library class in orthodox set-ups where the L8 compilation
      // is done in multiple steps, this is only partially supported (most notably for tests).
      assert holderClass.lookupMethod(retarget) != null;
      return retarget;
    }
    assert eventConsumer != null;
    ClasspathMethod ensuredMethod =
        appView
            .getSyntheticItems()
            .ensureFixedClasspathMethodFromType(
                retarget.getName(),
                retarget.getProto(),
                kinds -> kinds.RETARGET_STUB,
                retarget.getHolderType(),
                appView,
                ignored -> {},
                eventConsumer::acceptDesugaredLibraryRetargeterDispatchClasspathClass,
                methodBuilder ->
                    methodBuilder
                        .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
                        .setCode(null));
    assert ensuredMethod.getReference() == retarget;
    return retarget;
  }

  DexMethod forwardingMethod(EmulatedDispatchMethodDescriptor descriptor) {
    assert descriptor.getForwardingMethod().getHolderKind() == null;
    return descriptor.getForwardingMethod().getMethod();
  }

  public DexMethod ensureForwardingMethod(
      EmulatedDispatchMethodDescriptor descriptor,
      DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer) {
    return ensureRetargetMethod(forwardingMethod(descriptor), eventConsumer);
  }

  private boolean verifyKind(DerivedMethod method, SyntheticKindSelector kindSelector) {
    SyntheticKind kind = kindSelector.select(appView.getSyntheticItems().getNaming());
    assert method.getHolderKind().equals(kind);
    return true;
  }

  private DexMethod emulatedHolderDispatchMethod(DexType holder, DerivedMethod method) {
    assert verifyKind(method, kinds -> kinds.RETARGET_CLASS);
    DexProto newProto = appView.dexItemFactory().prependHolderToProto(method.getMethod());
    return appView.dexItemFactory().createMethod(holder, newProto, method.getName());
  }

  DexMethod emulatedInterfaceDispatchMethod(DexType holder, DerivedMethod method) {
    assert verifyKind(method, kinds -> kinds.RETARGET_INTERFACE);
    return appView.dexItemFactory().createMethod(holder, method.getProto(), method.getName());
  }

  public DexMethod emulatedInterfaceDispatchMethod(
      DexClass newInterface, EmulatedDispatchMethodDescriptor descriptor) {
    DexMethod method =
        emulatedInterfaceDispatchMethod(newInterface.type, descriptor.getInterfaceMethod());
    assert newInterface.lookupMethod(method) != null;
    return method;
  }

  public DexMethod ensureEmulatedHolderDispatchMethod(
      EmulatedDispatchMethodDescriptor descriptor,
      DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer) {
    assert eventConsumer != null;
    DerivedMethod emulatedDispatchMethod = descriptor.getEmulatedDispatchMethod();
    DexClass holderContext =
        appView.contextIndependentDefinitionFor(emulatedDispatchMethod.getHolderContext());
    DexClass syntheticClass;
    if (appView.options().isDesugaredLibraryCompilation()) {
      syntheticClass =
          appView
              .getSyntheticItems()
              .getExistingFixedClass(
                  ignored -> emulatedDispatchMethod.getHolderKind(), holderContext, appView);
      DexMethod dispatchMethod =
          emulatedHolderDispatchMethod(syntheticClass.type, emulatedDispatchMethod);
      assert syntheticClass.lookupMethod(dispatchMethod) != null;
      return dispatchMethod;
    } else {
      DexClass itfClass = ensureEmulatedInterfaceDispatchMethod(descriptor, eventConsumer);
      ClasspathOrLibraryClass context = holderContext.asClasspathOrLibraryClass();
      assert context != null;
      syntheticClass =
          appView
              .getSyntheticItems()
              .ensureFixedClasspathClass(
                  kinds -> kinds.RETARGET_CLASS,
                  context,
                  appView,
                  classBuilder ->
                      buildHolderDispatchMethod(classBuilder, itfClass, descriptor, eventConsumer),
                  eventConsumer::acceptDesugaredLibraryRetargeterDispatchClasspathClass);
    }
    DexMethod dispatchMethod =
        emulatedHolderDispatchMethod(syntheticClass.type, emulatedDispatchMethod);
    assert syntheticClass.lookupMethod(dispatchMethod) != null;
    return dispatchMethod;
  }

  public void ensureProgramEmulatedHolderDispatchMethod(
      EmulatedDispatchMethodDescriptor descriptor,
      DesugaredLibraryRetargeterL8SynthesizerEventConsumer eventConsumer) {
    assert eventConsumer != null;
    assert appView.options().isDesugaredLibraryCompilation();
    DerivedMethod emulatedDispatchMethod = descriptor.getEmulatedDispatchMethod();
    DexClass holderContext =
        appView.contextIndependentDefinitionFor(emulatedDispatchMethod.getHolderContext());
    DexClass itfClass = ensureEmulatedInterfaceDispatchMethod(descriptor, eventConsumer);
    appView
        .getSyntheticItems()
        .ensureFixedClass(
            ignored -> emulatedDispatchMethod.getHolderKind(),
            holderContext,
            appView,
            classBuilder -> buildHolderDispatchMethod(classBuilder, itfClass, descriptor, null),
            eventConsumer::acceptDesugaredLibraryRetargeterDispatchProgramClass);
  }

  public DexClass ensureEmulatedInterfaceDispatchMethod(
      EmulatedDispatchMethodDescriptor descriptor,
      DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer) {
    assert eventConsumer != null;
    DerivedMethod itfMethod = descriptor.getInterfaceMethod();
    DexClass itfContext = appView.contextIndependentDefinitionFor(itfMethod.getHolderContext());
    if (appView.options().isDesugaredLibraryCompilation()) {
      return appView
          .getSyntheticItems()
          .getExistingFixedClass(ignored -> itfMethod.getHolderKind(), itfContext, appView);
    }
    ClasspathOrLibraryClass context = itfContext.asClasspathOrLibraryClass();
    assert context != null;
    return appView
        .getSyntheticItems()
        .ensureFixedClasspathClass(
            kinds -> kinds.RETARGET_INTERFACE,
            context,
            appView,
            classBuilder -> buildInterfaceDispatchMethod(classBuilder, descriptor),
            eventConsumer::acceptDesugaredLibraryRetargeterDispatchClasspathClass);
  }

  public DexClass ensureEmulatedInterfaceDispatchMethod(
      EmulatedDispatchMethodDescriptor descriptor,
      DesugaredLibraryRetargeterL8SynthesizerEventConsumer eventConsumer) {
    assert appView.options().isDesugaredLibraryCompilation();
    assert eventConsumer != null;
    DerivedMethod itfMethod = descriptor.getInterfaceMethod();
    DexClass itfContext = appView.contextIndependentDefinitionFor(itfMethod.getHolderContext());
    return appView
        .getSyntheticItems()
        .ensureFixedClass(
            ignore -> itfMethod.getHolderKind(),
            itfContext,
            appView,
            classBuilder -> buildInterfaceDispatchMethod(classBuilder, descriptor),
            eventConsumer::acceptDesugaredLibraryRetargeterDispatchProgramClass);
  }

  private void buildInterfaceDispatchMethod(
      SyntheticClassBuilder<?, ?> classBuilder, EmulatedDispatchMethodDescriptor descriptor) {
    classBuilder
        .setInterface()
        .addMethod(
            methodBuilder -> {
              DexMethod itfMethod =
                  emulatedInterfaceDispatchMethod(
                      classBuilder.getType(), descriptor.getInterfaceMethod());
              MethodAccessFlags flags =
                  MethodAccessFlags.fromSharedAccessFlags(
                      Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT | Constants.ACC_SYNTHETIC,
                      false);
              methodBuilder
                  .setName(itfMethod.getName())
                  .setProto(itfMethod.getProto())
                  // Will be traced by the enqueuer.
                  .disableAndroidApiLevelCheck()
                  .setAccessFlags(flags);
            });
  }

  private <SCB extends SyntheticClassBuilder<?, ?>> void buildHolderDispatchMethod(
      SCB classBuilder,
      DexClass itfClass,
      EmulatedDispatchMethodDescriptor descriptor,
      DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer) {
    classBuilder.addMethod(
        methodBuilder -> {
          DexMethod dispatchMethod =
              emulatedHolderDispatchMethod(
                  classBuilder.getType(), descriptor.getEmulatedDispatchMethod());
          methodBuilder
              .setName(dispatchMethod.getName())
              .setProto(dispatchMethod.getProto())
              .setAccessFlags(MethodAccessFlags.createPublicStaticSynthetic())
              // Will be traced by the enqueuer.
              .disableAndroidApiLevelCheck()
              .setCode(
                  methodSig ->
                      appView.options().isDesugaredLibraryCompilation()
                          ? generateEmulatedDispatchCfCode(
                              descriptor, itfClass, methodSig, eventConsumer)
                          : null);
        });
  }

  private CfCode generateEmulatedDispatchCfCode(
      EmulatedDispatchMethodDescriptor descriptor,
      DexClass itfClass,
      DexMethod methodSig,
      DesugaredLibraryRetargeterInstructionEventConsumer eventConsumer) {
    DexMethod forwardingMethod = ensureForwardingMethod(descriptor, eventConsumer);
    DexMethod itfMethod = emulatedInterfaceDispatchMethod(itfClass, descriptor);
    assert descriptor.getDispatchCases().isEmpty();
    return new EmulateDispatchSyntheticCfCodeProvider(
            methodSig.getHolderType(), forwardingMethod, itfMethod, new LinkedHashMap<>(), appView)
        .generateCfCode();
  }
}
