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

import static com.android.tools.r8.apimodel.JavaSourceCodePrinter.Type.fromType;
import static com.android.tools.r8.ir.desugar.CovariantReturnTypeAnnotationTransformer.isCovariantReturnTypeAnnotation;
import static com.android.tools.r8.utils.MapUtils.ignoreKey;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.apimodel.JavaSourceCodePrinter;
import com.android.tools.r8.apimodel.JavaSourceCodePrinter.JavaSourceCodeMethodPrinter;
import com.android.tools.r8.apimodel.JavaSourceCodePrinter.KnownType;
import com.android.tools.r8.apimodel.JavaSourceCodePrinter.MethodParameter;
import com.android.tools.r8.apimodel.JavaSourceCodePrinter.ParameterizedType;
import com.android.tools.r8.cfmethodgeneration.MethodGenerationBase;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.utils.Action;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.ClassReferenceUtils;
import com.android.tools.r8.utils.EntryUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.MethodReferenceUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.google.common.collect.ImmutableList;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class GenerateCovariantReturnTypeMethodsTest extends TestBase {

  private static final String CLASS_NAME = "CovariantReturnTypeMethods";
  private static final String PACKAGE_NAME = "com.android.tools.r8.androidapi";
  // When updating to support a new api level build libcore in aosp and update the cloud dependency.
  private static final Path PATH_TO_CORE_JAR =
      Paths.get(ToolHelper.THIRD_PARTY_DIR, "android_jar", "libcore_latest", "core-oj.jar");
  private static final Path DESTINATION_FILE =
      Paths.get(ToolHelper.SOURCE_DIR)
          .resolve(PACKAGE_NAME.replace('.', '/'))
          .resolve(CLASS_NAME + ".java");
  private static final AndroidApiLevel GENERATED_FOR_API_LEVEL = AndroidApiLevel.T;

  @Parameter public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  @Test
  public void testLibCoreNeedsUpgrading() {
    assertEquals(GENERATED_FOR_API_LEVEL, AndroidApiLevel.LATEST);
  }

  @Test
  public void testCanFindAnnotatedMethodsInJar() throws Exception {
    CovariantMethodsInJarResult covariantMethodsInJar = CovariantMethodsInJarResult.create();
    // These assertions are here to ensure we produce a sane result.
    assertEquals(9, covariantMethodsInJar.methodReferenceMap.keySet().size());
    assertEquals(
        51, covariantMethodsInJar.methodReferenceMap.values().stream().mapToLong(List::size).sum());
  }

  @Test
  public void testGeneratedCodeUpToDate() throws Exception {
    assertEquals(FileUtils.readTextFile(DESTINATION_FILE, StandardCharsets.UTF_8), generateCode());
  }

  public static String generateCode() throws Exception {
    CovariantMethodsInJarResult covariantMethodsInJar = CovariantMethodsInJarResult.create();
    List<Entry<ClassReference, List<MethodReferenceWithApiLevel>>> entries =
        new ArrayList<>(covariantMethodsInJar.methodReferenceMap.entrySet());
    entries.sort(Entry.comparingByKey(ClassReferenceUtils.getClassReferenceComparator()));
    JavaSourceCodePrinter printer =
        JavaSourceCodePrinter.builder()
            .setHeader(
                MethodGenerationBase.getHeaderString(
                    2022, GenerateCovariantReturnTypeMethodsTest.class.getSimpleName()))
            .setPackageName(PACKAGE_NAME)
            .setClassName(CLASS_NAME)
            .build();
    String javaSourceCode =
        printer
            .addMethod(
                "public static",
                null,
                "registerMethodsWithCovariantReturnType",
                ImmutableList.of(
                    MethodParameter.build(fromType(KnownType.DexItemFactory), "factory"),
                    MethodParameter.build(
                        ParameterizedType.fromType(
                            KnownType.Consumer, fromType(KnownType.DexMethod)),
                        "consumer")),
                methodPrinter ->
                    entries.forEach(
                        EntryUtils.accept(
                            (ignored, covariations) -> {
                              covariations.sort(
                                  Comparator.comparing(
                                      MethodReferenceWithApiLevel::getMethodReference,
                                      MethodReferenceUtils.getMethodReferenceComparator()));
                              covariations.forEach(
                                  covariant ->
                                      registerCovariantMethod(
                                          methodPrinter, covariant.methodReference));
                            })))
            .toString();
    Path tempFile = Files.createTempFile("output-", ".java");
    Files.write(tempFile, javaSourceCode.getBytes(StandardCharsets.UTF_8));
    return MethodGenerationBase.formatRawOutput(tempFile);
  }

  private static void registerCovariantMethod(
      JavaSourceCodeMethodPrinter methodPrinter, MethodReference covariant) {
    methodPrinter
        .addInstanceMethodCall(
            "consumer",
            "accept",
            () ->
                methodPrinter.addInstanceMethodCall(
                    "factory",
                    "createMethod",
                    callCreateType(methodPrinter, covariant.getHolderClass().getDescriptor()),
                    callCreateProto(
                        methodPrinter,
                        covariant.getReturnType().getDescriptor(),
                        covariant.getFormalTypes().stream()
                            .map(TypeReference::getDescriptor)
                            .collect(Collectors.toList())),
                    methodPrinter.literal(covariant.getMethodName())))
        .addSemicolon()
        .newLine();
  }

  private static Action callCreateType(
      JavaSourceCodeMethodPrinter methodPrinter, String descriptor) {
    return () ->
        methodPrinter.addInstanceMethodCall(
            "factory", "createType", methodPrinter.literal(descriptor));
  }

  private static Action callCreateProto(
      JavaSourceCodeMethodPrinter methodPrinter,
      String returnTypeDescriptor,
      Collection<String> args) {
    List<Action> actionList = new ArrayList<>();
    actionList.add(callCreateType(methodPrinter, returnTypeDescriptor));
    for (String arg : args) {
      actionList.add(callCreateType(methodPrinter, arg));
    }
    return () -> methodPrinter.addInstanceMethodCall("factory", "createProto", actionList);
  }

  public static void main(String[] args) throws Exception {
    Files.write(DESTINATION_FILE, generateCode().getBytes(StandardCharsets.UTF_8));
  }

  public static class CovariantMethodsInJarResult {
    private final Map<ClassReference, List<MethodReferenceWithApiLevel>> methodReferenceMap;

    private CovariantMethodsInJarResult(
        Map<ClassReference, List<MethodReferenceWithApiLevel>> methodReferenceMap) {
      this.methodReferenceMap = methodReferenceMap;
    }

    public static CovariantMethodsInJarResult create() throws Exception {
      Map<ClassReference, List<MethodReferenceWithApiLevel>> methodReferenceMap = new HashMap<>();
      CodeInspector inspector = new CodeInspector(PATH_TO_CORE_JAR);
      DexItemFactory factory = inspector.getFactory();
      for (FoundClassSubject clazz : inspector.allClasses()) {
        clazz.forAllMethods(
            method -> {
              List<DexAnnotation> covariantAnnotations =
                  inspector.findAnnotations(
                      method.getMethod().annotations(),
                      annotation ->
                          isCovariantReturnTypeAnnotation(annotation.annotation, factory));
              if (!covariantAnnotations.isEmpty()) {
                MethodReference methodReference = method.asMethodReference();
                ClassReference holder = clazz.getOriginalReference();
                for (DexAnnotation covariantAnnotation : covariantAnnotations) {
                  if (covariantAnnotation.annotation.type
                      == factory.annotationCovariantReturnType) {
                    createCovariantMethodReference(
                        methodReference, covariantAnnotation, methodReferenceMap);
                  } else {
                    fail("There are no such annotations present in libcore");
                  }
                }
              }
            });
      }
      return new CovariantMethodsInJarResult(methodReferenceMap);
    }

    private static void createCovariantMethodReference(
        MethodReference methodReference,
        DexAnnotation covariantAnnotation,
        Map<ClassReference, List<MethodReferenceWithApiLevel>> methodReferenceMap) {
      DexValueType newReturnType =
          covariantAnnotation.annotation.getElement(0).getValue().asDexValueType();
      DexAnnotationElement element = covariantAnnotation.annotation.getElement(1);
      assert element.name.toString().equals("presentAfter");
      AndroidApiLevel apiLevel =
          AndroidApiLevel.getAndroidApiLevel(element.getValue().asDexValueInt().value);
      methodReferenceMap
          .computeIfAbsent(methodReference.getHolderClass(), ignoreKey(ArrayList::new))
          .add(
              new MethodReferenceWithApiLevel(
                  Reference.method(
                      methodReference.getHolderClass(),
                      methodReference.getMethodName(),
                      methodReference.getFormalTypes(),
                      newReturnType.value.asClassReference()),
                  apiLevel));
    }

    public void visitCovariantMethodsForHolder(
        ClassReference reference, Consumer<MethodReferenceWithApiLevel> consumer) {
      List<MethodReferenceWithApiLevel> methodReferences = methodReferenceMap.get(reference);
      if (methodReferences != null) {
        methodReferences.stream()
            .sorted(
                Comparator.comparing(
                    MethodReferenceWithApiLevel::getMethodReference,
                    MethodReferenceUtils.getMethodReferenceComparator()))
            .forEach(consumer);
      }
    }
  }

  public static class MethodReferenceWithApiLevel {

    private final MethodReference methodReference;
    private final AndroidApiLevel apiLevel;

    private MethodReferenceWithApiLevel(MethodReference methodReference, AndroidApiLevel apiLevel) {
      this.methodReference = methodReference;
      this.apiLevel = apiLevel;
    }

    public MethodReference getMethodReference() {
      return methodReference;
    }

    public AndroidApiLevel getApiLevel() {
      return apiLevel;
    }
  }
}
