// 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.ir.desugar;

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.ClassAccessFlags;
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexApplication;
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.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.DexTypeList;
import com.android.tools.r8.graph.FieldAccessFlags;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterConstructorCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterThrowRuntimeExceptionCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterVivifiedWrapperCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperCfCodeProvider;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConverterWrapperConversionCfCodeProvider;
import com.android.tools.r8.origin.SynthesizedOrigin;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;

// I am responsible for the generation of wrappers used to call library APIs when desugaring
// libraries. Wrappers can be both ways, wrapping the desugarType as a type, or the type as
// a desugar type.
// This file use the vivifiedType -> type, type -> desugarType convention described in the
// DesugaredLibraryAPIConverter class.
// Wrappers contain the following:
// - a single static method convert, which is used by the DesugaredLibraryAPIConverter for
// conversion, it's the main public API (public).
// - a constructor setting the wrappedValue (private).
// - a getter for the wrappedValue (public unwrap()).
// - a single instance field holding the wrapped value (private final).
// - a copy of all implemented methods in the class/interface wrapped. Such methods only do type
// conversions and forward the call to the wrapped type. Parameters and return types are also
// converted.
// Generation of the conversion method in the wrappers is postponed until the compiler knows if the
// reversed wrapper is needed.

// Example of the type wrapper ($-WRP) of java.util.BiFunction at the end of the compilation. I
// omitted
// generic values for simplicity and wrote .... instead of .util.function. Note the difference
// between $-WRP and $-V-WRP wrappers:
// public class j$....BiFunction$-WRP implements java....BiFunction {
//   private final j$....BiFunction wrappedValue;
//   private BiFunction (j$....BiFunction wrappedValue) {
//     this.wrappedValue = wrappedValue;
//   }
//   public R apply(T t, U u) {
//     return wrappedValue.apply(t, u);
//   }
//   public BiFunction andThen(java....Function after) {
//     j$....BiFunction afterConverted = j$....BiFunction$-V-WRP.convert(after);
//     return wrappedValue.andThen(afterConverted);
//   }
//   public static convert(j$....BiFunction function){
//     if (function == null) {
//       return null;
//     }
//     if (function instanceof j$....BiFunction$-V-WRP) {
//       return ((j$....BiFunction$-V-WRP) function).wrappedValue;
//     }
//     return new j$....BiFunction$-WRP(wrappedValue);
//     }
//   }
public class DesugaredLibraryWrapperSynthesizer {

  public static final String WRAPPER_PREFIX = "$r8$wrapper$";
  public static final String WRAPPER_DESCRIPTOR_PREFIX = "L" + WRAPPER_PREFIX;
  public static final String TYPE_WRAPPER_SUFFIX = "$-WRP";
  public static final String VIVIFIED_TYPE_WRAPPER_SUFFIX = "$-V-WRP";

  private final AppView<?> appView;
  private final Map<DexType, Pair<DexType, DexProgramClass>> typeWrappers =
      new ConcurrentHashMap<>();
  private final Map<DexType, Pair<DexType, DexProgramClass>> vivifiedTypeWrappers =
      new ConcurrentHashMap<>();
  // The invalidWrappers are wrappers with incorrect behavior because of final methods that could
  // not be overridden. Such wrappers are awful because the runtime behavior is undefined and does
  // not raise explicit errors. So we register them here and conversion methods for such wrappers
  // raise a runtime exception instead of generating the wrapper.
  private final Set<DexType> invalidWrappers = Sets.newConcurrentHashSet();
  private final Set<DexType> generatedWrappers = Sets.newConcurrentHashSet();
  private final DexItemFactory factory;
  private final DesugaredLibraryAPIConverter converter;

  DesugaredLibraryWrapperSynthesizer(AppView<?> appView, DesugaredLibraryAPIConverter converter) {
    this.appView = appView;
    this.factory = appView.dexItemFactory();
    this.converter = converter;
  }

  public static boolean isSynthesizedWrapper(DexType clazz) {
    return clazz.descriptor.toString().startsWith(WRAPPER_DESCRIPTOR_PREFIX);
  }

  boolean hasSynthesized(DexType type) {
    return generatedWrappers.contains(type);
  }

  // Wrapper initial generation section.
  // 1. Generate wrappers without conversion methods.
  // 2. Compute wrapper types.

  boolean canGenerateWrapper(DexType type) {
    DexClass dexClass = appView.definitionFor(type);
    if (dexClass == null) {
      return false;
    }
    return dexClass.isLibraryClass();
  }

  DexType getTypeWrapper(DexType type) {
    return getWrapper(type, TYPE_WRAPPER_SUFFIX, typeWrappers, this::generateTypeWrapper);
  }

  DexType getVivifiedTypeWrapper(DexType type) {
    return getWrapper(
        type,
        VIVIFIED_TYPE_WRAPPER_SUFFIX,
        vivifiedTypeWrappers,
        this::generateVivifiedTypeWrapper);
  }

  private DexType createWrapperType(DexType type, String suffix) {
    return factory.createType(
        DescriptorUtils.javaTypeToDescriptor(
            WRAPPER_PREFIX + type.toString().replace('.', '$') + suffix));
  }

  private DexType getWrapper(
      DexType type,
      String suffix,
      Map<DexType, Pair<DexType, DexProgramClass>> wrappers,
      BiFunction<DexClass, DexType, DexProgramClass> wrapperGenerator) {
    // Answers the DexType of the wrapper. Generate the wrapper DexProgramClass if not already done,
    // except the conversions methods. Conversion method generation is postponed to know if the
    // reverse wrapper is present at generation time.
    // We generate the type while locking the concurrent hash map, but we release the lock before
    // generating the actual class to avoid locking for too long (hence the Pair).
    assert !type.toString().startsWith(DesugaredLibraryAPIConverter.VIVIFIED_PREFIX);
    Box<Boolean> toGenerate = new Box<>(false);
    Pair<DexType, DexProgramClass> pair =
        wrappers.computeIfAbsent(
            type,
            t -> {
              toGenerate.set(true);
              DexType wrapperType = createWrapperType(type, suffix);
              generatedWrappers.add(wrapperType);
              return new Pair<>(wrapperType, null);
            });
    if (toGenerate.get()) {
      assert pair.getSecond() == null;
      DexClass dexClass = appView.definitionFor(type);
      // The dexClass should be a library class, so it cannot be null.
      assert dexClass != null && dexClass.isLibraryClass();
      if (dexClass.accessFlags.isFinal()) {
        throw appView
            .options()
            .reporter
            .fatalError(
                new StringDiagnostic(
                    "Cannot generate a wrapper for final class "
                        + dexClass.type
                        + ". Add a custom conversion in the desugared library."));
      }
      pair.setSecond(wrapperGenerator.apply(dexClass, pair.getFirst()));
    }
    return pair.getFirst();
  }

  private DexType vivifiedTypeFor(DexType type) {
    return DesugaredLibraryAPIConverter.vivifiedTypeFor(type, appView);
  }

  private DexProgramClass generateTypeWrapper(DexClass dexClass, DexType typeWrapperType) {
    DexType type = dexClass.type;
    DexEncodedField wrapperField = synthesizeWrappedValueField(typeWrapperType, type);
    return synthesizeWrapper(
        vivifiedTypeFor(type),
        dexClass,
        synthesizeVirtualMethodsForTypeWrapper(dexClass.asLibraryClass(), wrapperField),
        wrapperField);
  }

  private DexProgramClass generateVivifiedTypeWrapper(
      DexClass dexClass, DexType vivifiedTypeWrapperType) {
    DexType type = dexClass.type;
    DexEncodedField wrapperField =
        synthesizeWrappedValueField(vivifiedTypeWrapperType, vivifiedTypeFor(type));
    return synthesizeWrapper(
        type,
        dexClass,
        synthesizeVirtualMethodsForVivifiedTypeWrapper(dexClass.asLibraryClass(), wrapperField),
        wrapperField);
  }

  private DexProgramClass synthesizeWrapper(
      DexType wrappingType,
      DexClass clazz,
      DexEncodedMethod[] virtualMethods,
      DexEncodedField wrapperField) {
    boolean isItf = clazz.isInterface();
    DexType superType = isItf ? factory.objectType : wrappingType;
    DexTypeList interfaces =
        isItf ? new DexTypeList(new DexType[] {wrappingType}) : DexTypeList.empty();
    return new DexProgramClass(
        wrapperField.field.holder,
        null,
        new SynthesizedOrigin("Desugared library API Converter", getClass()),
        ClassAccessFlags.fromSharedAccessFlags(
            Constants.ACC_FINAL | Constants.ACC_SYNTHETIC | Constants.ACC_PUBLIC),
        superType,
        interfaces,
        clazz.sourceFile,
        null,
        Collections.emptyList(),
        null,
        Collections.emptyList(),
        DexAnnotationSet.empty(),
        DexEncodedField.EMPTY_ARRAY, // No static fields.
        new DexEncodedField[] {wrapperField},
        new DexEncodedMethod[] {
          synthesizeConstructor(wrapperField.field)
        }, // Conversions methods will be added later.
        virtualMethods,
        factory.getSkipNameValidationForTesting(),
        Collections.emptyList());
  }

  private DexEncodedMethod[] synthesizeVirtualMethodsForVivifiedTypeWrapper(
      DexLibraryClass dexClass, DexEncodedField wrapperField) {
    List<DexEncodedMethod> dexMethods = allImplementedMethods(dexClass);
    List<DexEncodedMethod> generatedMethods = new ArrayList<>();
    // Each method should use only types in their signature, but each method the wrapper forwards
    // to should used only vivified types.
    // Generated method looks like:
    // long foo (type, int)
    //   v0 <- arg0;
    //   v1 <- arg1;
    //   v2 <- convertTypeToVivifiedType(v0);
    //   v3 <- wrappedValue.foo(v2,v1);
    //   return v3;
    Set<DexMethod> finalMethods = Sets.newIdentityHashSet();
    for (DexEncodedMethod dexEncodedMethod : dexMethods) {
      DexClass holderClass = appView.definitionFor(dexEncodedMethod.method.holder);
      assert holderClass != null;
      DexMethod methodToInstall =
          factory.createMethod(
              wrapperField.field.holder,
              dexEncodedMethod.method.proto,
              dexEncodedMethod.method.name);
      CfCode cfCode;
      if (dexEncodedMethod.isFinal()) {
        invalidWrappers.add(wrapperField.field.holder);
        finalMethods.add(dexEncodedMethod.method);
        continue;
      } else {
        cfCode =
            new APIConverterVivifiedWrapperCfCodeProvider(
                    appView,
                    methodToInstall,
                    wrapperField.field,
                    converter,
                    holderClass.isInterface())
                .generateCfCode();
      }
      DexEncodedMethod newDexEncodedMethod =
          newSynthesizedMethod(methodToInstall, dexEncodedMethod, cfCode);
      generatedMethods.add(newDexEncodedMethod);
    }
    return finalizeWrapperMethods(generatedMethods, finalMethods);
  }

  private DexEncodedMethod[] synthesizeVirtualMethodsForTypeWrapper(
      DexLibraryClass dexClass, DexEncodedField wrapperField) {
    List<DexEncodedMethod> dexMethods = allImplementedMethods(dexClass);
    List<DexEncodedMethod> generatedMethods = new ArrayList<>();
    // Each method should use only vivified types in their signature, but each method the wrapper
    // forwards
    // to should used only types.
    // Generated method looks like:
    // long foo (type, int)
    //   v0 <- arg0;
    //   v1 <- arg1;
    //   v2 <- convertVivifiedTypeToType(v0);
    //   v3 <- wrappedValue.foo(v2,v1);
    //   return v3;
    Set<DexMethod> finalMethods = Sets.newIdentityHashSet();
    for (DexEncodedMethod dexEncodedMethod : dexMethods) {
      DexClass holderClass = appView.definitionFor(dexEncodedMethod.method.holder);
      assert holderClass != null;
      DexMethod methodToInstall =
          DesugaredLibraryAPIConverter.methodWithVivifiedTypeInSignature(
              dexEncodedMethod.method, wrapperField.field.holder, appView);
      CfCode cfCode;
      if (dexEncodedMethod.isFinal()) {
        invalidWrappers.add(wrapperField.field.holder);
        finalMethods.add(dexEncodedMethod.method);
        continue;
      } else {
        cfCode =
            new APIConverterWrapperCfCodeProvider(
                    appView,
                    dexEncodedMethod.method,
                    wrapperField.field,
                    converter,
                    holderClass.isInterface())
                .generateCfCode();
      }
      DexEncodedMethod newDexEncodedMethod =
          newSynthesizedMethod(methodToInstall, dexEncodedMethod, cfCode);
      generatedMethods.add(newDexEncodedMethod);
    }
    return finalizeWrapperMethods(generatedMethods, finalMethods);
  }

  private DexEncodedMethod[] finalizeWrapperMethods(
      List<DexEncodedMethod> generatedMethods, Set<DexMethod> finalMethods) {
    if (finalMethods.isEmpty()) {
      return generatedMethods.toArray(DexEncodedMethod.EMPTY_ARRAY);
    }
    // Wrapper is invalid, no need to add the virtual methods.
    reportFinalMethodsInWrapper(finalMethods);
    return DexEncodedMethod.EMPTY_ARRAY;
  }

  private void reportFinalMethodsInWrapper(Set<DexMethod> methods) {
    String[] methodArray =
        methods.stream().map(method -> method.holder + "#" + method.name).toArray(String[]::new);
    appView
        .options()
        .reporter
        .info(
            new StringDiagnostic(
                "Desugared library API conversion: cannot wrap final methods "
                    + Arrays.toString(methodArray)
                    + ". "
                    + methods.iterator().next().holder
                    + " is marked as invalid and will throw a runtime exception upon conversion."));
  }

  DexEncodedMethod newSynthesizedMethod(
      DexMethod methodToInstall, DexEncodedMethod template, Code code) {
    MethodAccessFlags newFlags = template.accessFlags.copy();
    assert newFlags.isPublic();
    newFlags.unsetAbstract();
    newFlags.setSynthetic();
    return new DexEncodedMethod(
        methodToInstall,
        newFlags,
        DexAnnotationSet.empty(),
        ParameterAnnotationsList.empty(),
        code);
  }

  private List<DexEncodedMethod> allImplementedMethods(DexLibraryClass libraryClass) {
    LinkedList<DexClass> workList = new LinkedList<>();
    List<DexEncodedMethod> implementedMethods = new ArrayList<>();
    workList.add(libraryClass);
    while (!workList.isEmpty()) {
      DexClass dexClass = workList.removeFirst();
      for (DexEncodedMethod virtualMethod : dexClass.virtualMethods()) {
        if (!virtualMethod.isPrivateMethod()) {
          boolean alreadyAdded = false;
          // This looks quadratic but given the size of the collections met in practice for
          // desugared libraries (Max ~15) it does not matter.
          for (DexEncodedMethod alreadyImplementedMethod : implementedMethods) {
            if (alreadyImplementedMethod.method.match(virtualMethod.method)) {
              alreadyAdded = true;
              continue;
            }
          }
          if (!alreadyAdded) {
            implementedMethods.add(virtualMethod);
          }
        }
      }
      for (DexType itf : dexClass.interfaces.values) {
        DexClass itfClass = appView.definitionFor(itf);
        assert itfClass != null; // Cannot be null since we started from a LibraryClass.
        workList.add(itfClass);
      }
      if (dexClass.superType != factory.objectType) {
        DexClass superClass = appView.definitionFor(dexClass.superType);
        assert superClass != null; // Cannot be null since we started from a LibraryClass.
        workList.add(superClass);
      }
    }
    // 10 is large enough to avoid warnings on Clock/Function, but not on Stream.
    if (implementedMethods.size() > 10) {
      appView
          .options()
          .reporter
          .info(
              new StringDiagnostic(
                  "Desugared library API conversion: Generating a large wrapper for "
                      + libraryClass.type
                      + ". Is that the intended behavior?"));
    }
    return implementedMethods;
  }

  private DexEncodedField synthesizeWrappedValueField(DexType holder, DexType fieldType) {
    DexField field = factory.createField(holder, fieldType, factory.wrapperFieldName);
    // Field is package private to be accessible from convert methods without a getter.
    FieldAccessFlags fieldAccessFlags =
        FieldAccessFlags.fromCfAccessFlags(Constants.ACC_FINAL | Constants.ACC_SYNTHETIC);
    return new DexEncodedField(field, fieldAccessFlags, DexAnnotationSet.empty(), null);
  }

  private DexEncodedMethod synthesizeConstructor(DexField field) {
    DexMethod method =
        factory.createMethod(
            field.holder,
            factory.createProto(factory.voidType, field.type),
            factory.initMethodName);
    return newSynthesizedMethod(
        method,
        Constants.ACC_PRIVATE | Constants.ACC_SYNTHETIC,
        true,
        new APIConverterConstructorCfCodeProvider(appView, field).generateCfCode());
  }

  private DexEncodedMethod newSynthesizedMethod(
      DexMethod methodToInstall, int flags, boolean constructor, Code code) {
    MethodAccessFlags accessFlags = MethodAccessFlags.fromSharedAccessFlags(flags, constructor);
    return new DexEncodedMethod(
        methodToInstall,
        accessFlags,
        DexAnnotationSet.empty(),
        ParameterAnnotationsList.empty(),
        code);
  }

  // Wrapper finalization section.
  // 1. Generate conversions methods (convert(type)).
  // 2. Add the synthesized classes.
  // 3. Process all methods.

  void finalizeWrappers(
      DexApplication.Builder<?> builder, IRConverter irConverter, ExecutorService executorService)
      throws ExecutionException {
    finalizeWrappers(
        builder, irConverter, executorService, typeWrappers, this::generateTypeConversions);
    finalizeWrappers(
        builder,
        irConverter,
        executorService,
        vivifiedTypeWrappers,
        this::generateVivifiedTypeConversions);
  }

  private void finalizeWrappers(
      DexApplication.Builder<?> builder,
      IRConverter irConverter,
      ExecutorService executorService,
      Map<DexType, Pair<DexType, DexProgramClass>> wrappers,
      BiConsumer<DexType, DexProgramClass> generateConversions)
      throws ExecutionException {
    assert verifyAllClassesGenerated();
    for (DexType type : wrappers.keySet()) {
      DexProgramClass pgrmClass = wrappers.get(type).getSecond();
      assert pgrmClass != null;
      generateConversions.accept(type, pgrmClass);
      registerSynthesizedClass(pgrmClass, builder);
      irConverter.optimizeSynthesizedClass(pgrmClass, executorService);
    }
  }

  private boolean verifyAllClassesGenerated() {
    for (Pair<DexType, DexProgramClass> pair : vivifiedTypeWrappers.values()) {
      assert pair.getSecond() != null;
    }
    for (Pair<DexType, DexProgramClass> pair : typeWrappers.values()) {
      assert pair.getSecond() != null;
    }
    return true;
  }

  private void registerSynthesizedClass(
      DexProgramClass synthesizedClass, DexApplication.Builder<?> builder) {
    builder.addSynthesizedClass(synthesizedClass, false);
    appView.appInfo().addSynthesizedClass(synthesizedClass);
  }

  private void generateTypeConversions(DexType type, DexProgramClass synthesizedClass) {
    Pair<DexType, DexProgramClass> reverse = vivifiedTypeWrappers.get(type);
    assert reverse == null || reverse.getSecond() != null;
    synthesizedClass.addDirectMethod(
        synthesizeConversionMethod(
            synthesizedClass.type,
            type,
            type,
            vivifiedTypeFor(type),
            reverse == null ? null : reverse.getSecond()));
  }

  private void generateVivifiedTypeConversions(DexType type, DexProgramClass synthesizedClass) {
    Pair<DexType, DexProgramClass> reverse = typeWrappers.get(type);
    synthesizedClass.addDirectMethod(
        synthesizeConversionMethod(
            synthesizedClass.type,
            type,
            vivifiedTypeFor(type),
            type,
            reverse == null ? null : reverse.getSecond()));
  }

  private DexEncodedMethod synthesizeConversionMethod(
      DexType holder,
      DexType type,
      DexType argType,
      DexType returnType,
      DexClass reverseWrapperClassOrNull) {
    DexMethod method =
        factory.createMethod(
            holder, factory.createProto(returnType, argType), factory.convertMethodName);
    CfCode cfCode;
    if (invalidWrappers.contains(holder)) {
      cfCode =
          new APIConverterThrowRuntimeExceptionCfCodeProvider(
                  appView,
                  factory.createString(
                      "Unsupported conversion for "
                          + type
                          + ". See compilation time infos for more details."),
                  holder)
              .generateCfCode();
    } else {
      DexField uniqueFieldOrNull =
          reverseWrapperClassOrNull == null
              ? null
              : reverseWrapperClassOrNull.instanceFields().get(0).field;
      cfCode =
          new APIConverterWrapperConversionCfCodeProvider(
                  appView,
                  argType,
                  uniqueFieldOrNull,
                  factory.createField(holder, returnType, factory.wrapperFieldName))
              .generateCfCode();
    }
    return newSynthesizedMethod(
        method,
        Constants.ACC_SYNTHETIC | Constants.ACC_STATIC | Constants.ACC_PUBLIC,
        false,
        cfCode);
  }
}
