// 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.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GenericSignature.ClassTypeSignature;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaring;
import com.android.tools.r8.ir.desugar.CfPostProcessingDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeterSynthesizerEventConsumer.DesugaredLibraryRetargeterPostProcessingEventConsumer;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.collections.DexClassAndMethodSet;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;

// The rewrite of virtual calls requires to go through emulate dispatch. This class is responsible
// for inserting interfaces on library boundaries and forwarding methods in the program, and to
// synthesize the interfaces and emulated dispatch classes in the desugared library.
public class DesugaredLibraryRetargeterPostProcessor implements CfPostProcessingDesugaring {

  private final AppView<?> appView;
  private final DesugaredLibraryRetargeterSyntheticHelper syntheticHelper;
  private final DexClassAndMethodSet emulatedDispatchMethods;

  public DesugaredLibraryRetargeterPostProcessor(
      AppView<?> appView, RetargetingInfo retargetingInfo) {
    this.appView = appView;
    this.syntheticHelper = new DesugaredLibraryRetargeterSyntheticHelper(appView);
    emulatedDispatchMethods = retargetingInfo.getEmulatedDispatchMethods();
  }

  @Override
  public void postProcessingDesugaring(
      Collection<DexProgramClass> programClasses,
      CfPostProcessingDesugaringEventConsumer eventConsumer,
      ExecutorService executorService)
      throws ExecutionException {
    assert !appView.options().isDesugaredLibraryCompilation();
    ensureInterfacesAndForwardingMethodsSynthesized(programClasses, eventConsumer);
  }

  private void ensureInterfacesAndForwardingMethodsSynthesized(
      Collection<DexProgramClass> programClasses,
      DesugaredLibraryRetargeterPostProcessingEventConsumer eventConsumer) {
    assert !appView.options().isDesugaredLibraryCompilation();
    Map<DexType, List<DexClassAndMethod>> map = Maps.newIdentityHashMap();
    for (DexClassAndMethod emulatedDispatchMethod : emulatedDispatchMethods) {
      map.putIfAbsent(emulatedDispatchMethod.getHolderType(), new ArrayList<>(1));
      map.get(emulatedDispatchMethod.getHolderType()).add(emulatedDispatchMethod);
    }
    for (DexProgramClass clazz : programClasses) {
      if (clazz.superType == null) {
        assert clazz.type == appView.dexItemFactory().objectType : clazz.type.toSourceString();
        continue;
      }
      DexClass superclass = appView.definitionFor(clazz.superType);
      // Only performs computation if superclass is a library class, but not object to filter out
      // the most common case.
      if (superclass != null
          && superclass.isLibraryClass()
          && superclass.type != appView.dexItemFactory().objectType) {
        map.forEach(
            (type, methods) -> {
              if (inherit(superclass.asLibraryClass(), type, emulatedDispatchMethods)) {
                ensureInterfacesAndForwardingMethodsSynthesized(eventConsumer, clazz, methods);
              }
            });
      }
    }
  }

  private boolean inherit(
      DexLibraryClass clazz, DexType typeToInherit, DexClassAndMethodSet retarget) {
    DexLibraryClass current = clazz;
    while (current.type != appView.dexItemFactory().objectType) {
      if (current.type == typeToInherit) {
        return true;
      }
      DexClass dexClass = appView.definitionFor(current.superType);
      if (dexClass == null || dexClass.isClasspathClass()) {
        reportInvalidLibrarySupertype(current, retarget);
        return false;
      } else if (dexClass.isProgramClass()) {
        // If dexClass is a program class, then it is already correctly desugared.
        return false;
      }
      current = dexClass.asLibraryClass();
    }
    return false;
  }

  private void ensureInterfacesAndForwardingMethodsSynthesized(
      DesugaredLibraryRetargeterPostProcessingEventConsumer eventConsumer,
      DexProgramClass clazz,
      List<DexClassAndMethod> methods) {
    // DesugaredLibraryRetargeter emulate dispatch: insertion of a marker interface & forwarding
    // methods.
    // We cannot use the ClassProcessor since this applies up to 26, while the ClassProcessor
    // applies up to 24.
    if (appView.isAlreadyLibraryDesugared(clazz)) {
      return;
    }
    for (DexClassAndMethod method : methods) {
      DexClass newInterface =
          syntheticHelper.ensureEmulatedInterfaceDispatchMethod(method, eventConsumer);
      if (clazz.interfaces.contains(newInterface.type)) {
        // The class has already been desugared.
        continue;
      }
      if (appView
          .options()
          .desugaredLibrarySpecification
          .getDontRetargetLibMember()
          .contains(clazz.getType())) {
        continue;
      }
      clazz.addExtraInterfaces(
          Collections.singletonList(new ClassTypeSignature(newInterface.type)));
      eventConsumer.acceptInterfaceInjection(clazz, newInterface);
      if (clazz.lookupVirtualMethod(method.getReference()) == null) {
        DexEncodedMethod newMethod = createForwardingMethod(method, clazz);
        clazz.addVirtualMethod(newMethod);
        eventConsumer.acceptForwardingMethod(new ProgramMethod(clazz, newMethod));
      }
    }
  }

  private DexEncodedMethod createForwardingMethod(DexClassAndMethod target, DexClass clazz) {
    // NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
    // even if this results in invalid code, these classes are never desugared.
    // In desugared library, emulated interface methods can be overridden by retarget lib members.
    DexMethod forwardMethod =
        appView.options().desugaredLibrarySpecification.retargetMethod(target, appView);
    assert forwardMethod != null && forwardMethod != target.getReference();
    DexEncodedMethod desugaringForwardingMethod =
        DexEncodedMethod.createDesugaringForwardingMethod(
            target, clazz, forwardMethod, appView.dexItemFactory());
    desugaringForwardingMethod.setLibraryMethodOverride(OptionalBool.TRUE);
    return desugaringForwardingMethod;
  }

  private void reportInvalidLibrarySupertype(
      DexLibraryClass libraryClass, DexClassAndMethodSet retarget) {
    DexClass dexClass = appView.definitionFor(libraryClass.superType);
    String message;
    if (dexClass == null) {
      message = "missing";
    } else if (dexClass.isClasspathClass()) {
      message = "a classpath class";
    } else {
      message = "INVALID";
      assert false;
    }
    appView
        .options()
        .warningInvalidLibrarySuperclassForDesugar(
            dexClass == null ? libraryClass.getOrigin() : dexClass.getOrigin(),
            libraryClass.type,
            libraryClass.superType,
            message,
            retarget);
  }
}
