// 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.kotlin.metadata;

import static com.android.tools.r8.KotlinCompilerTool.KOTLINC;
import static com.android.tools.r8.utils.codeinspector.Matchers.isDexClass;
import static com.android.tools.r8.utils.codeinspector.Matchers.isExtensionFunction;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isRenamed;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.KmClassSubject;
import com.android.tools.r8.utils.codeinspector.KmFunctionSubject;
import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
import com.android.tools.r8.utils.codeinspector.KmPropertySubject;
import com.android.tools.r8.utils.codeinspector.KmTypeParameterSubject;
import com.android.tools.r8.utils.codeinspector.KmTypeParameterSubjectMixin;
import com.android.tools.r8.utils.codeinspector.KmTypeProjectionSubject;
import com.android.tools.r8.utils.codeinspector.KmTypeSubject;
import com.android.tools.r8.utils.codeinspector.KmValueParameterSubject;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import kotlinx.metadata.KmClassifier.TypeParameter;
import kotlinx.metadata.KmVariance;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class MetadataRewriteInTypeArgumentsTest extends KotlinMetadataTestBase {

  private static final String LIB_PKG = PKG + ".typeargument_lib.";

  private static int FLAG_NONE = 0;
  private static int FLAG_REIFIED = 1;

  private static final String EXPECTED =
      StringUtils.lines(
          "Hello World!",
          "42",
          "1",
          "42",
          "42",
          "1",
          "42",
          "42",
          "42",
          "1",
          "42",
          "1",
          "42",
          "42",
          "42",
          "42",
          "42",
          "1",
          "2",
          "9",
          "3",
          "7",
          "9",
          "42",
          "42",
          "7");

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0} target: {1}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters().withCfRuntimes().build(), KotlinTargetVersion.values());
  }

  public MetadataRewriteInTypeArgumentsTest(
      TestParameters parameters, KotlinTargetVersion targetVersion) {
    super(targetVersion);
    this.parameters = parameters;
  }

  private static final Map<KotlinTargetVersion, Path> jarMap = new HashMap<>();

  @BeforeClass
  public static void createLibJar() throws Exception {
    String typeAliasLibFolder = PKG_PREFIX + "/typeargument_lib";
    for (KotlinTargetVersion targetVersion : KotlinTargetVersion.values()) {
      Path typeAliasLibJar =
          kotlinc(KOTLINC, targetVersion)
              .addSourceFiles(getKotlinFileInTest(typeAliasLibFolder, "lib"))
              .compile();
      jarMap.put(targetVersion, typeAliasLibJar);
    }
  }

  @Test
  public void smokeTest() throws Exception {
    Path libJar = jarMap.get(targetVersion);

    Path output =
        kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
            .addClasspathFiles(libJar)
            .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/typeargument_app", "main"))
            .setOutputPath(temp.newFolder().toPath())
            .compile();

    testForJvm()
        .addRunClasspathFiles(ToolHelper.getKotlinStdlibJar(), libJar)
        .addClasspath(output)
        .run(parameters.getRuntime(), PKG + ".typeargument_app.MainKt")
        .assertSuccessWithOutput(EXPECTED);
  }

  @Test
  public void testMetadataInTypeAliasWithR8() throws Exception {
    Path libJar =
        testForR8(parameters.getBackend())
            .addProgramFiles(jarMap.get(targetVersion))
            // Keep ClassThatWillBeObfuscated, but allow minification.
            .addKeepRules("-keep,allowobfuscation class **ClassThatWillBeObfuscated")
            .addKeepRules("-keepclassmembers class **ClassThatWillBeObfuscated { *; }")
            // Keep all other classes.
            .addKeepRules("-keep class **typeargument_lib.PlainBox { *; }")
            .addKeepRules("-keep class **typeargument_lib.SomeClass { *; }")
            .addKeepRules("-keep class **typeargument_lib.CoVariant { *; }")
            .addKeepRules("-keep class **typeargument_lib.ContraVariant { *; }")
            .addKeepRules("-keep class **typeargument_lib.Invariant { *; }")
            .addKeepRules("-keep class **typeargument_lib.LibKt { *; }")
            .addKeepAttributes(
                ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS,
                ProguardKeepAttributes.SIGNATURE,
                ProguardKeepAttributes.INNER_CLASSES,
                ProguardKeepAttributes.ENCLOSING_METHOD)
            .compile()
            .inspect(this::inspect)
            .writeToZip();

    // TODO(b/152306391): Reified type-parameters are not flagged correctly.
    ProcessResult mainResult =
        kotlinc(parameters.getRuntime().asCf(), KOTLINC, targetVersion)
            .addClasspathFiles(libJar)
            .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/typeargument_app", "main"))
            .setOutputPath(temp.newFolder().toPath())
            .compileRaw();
    assertEquals(1, mainResult.exitCode);
    assertThat(
        mainResult.stderr,
        containsString(
            "org.jetbrains.kotlin.codegen.CompilationException: "
                + "Back-end (JVM) Internal error: wrong bytecode generated"));
  }

  private void inspect(CodeInspector inspector) {
    inspectInvariant(inspector);
    inspectCoVariant(inspector);
    inspectContraVariant(inspector);
    inspectExtensions(inspector);
  }

  private void inspectInvariant(CodeInspector inspector) {
    ClassSubject someClass = inspector.clazz(LIB_PKG + "SomeClass");
    assertThat(someClass, isPresent());
    ClassSubject classThatShouldBeObfuscated =
        inspector.clazz(LIB_PKG + "ClassThatWillBeObfuscated");
    assertThat(classThatShouldBeObfuscated, isRenamed());

    // Check that the type-parameters of Invariant is marked as INVARIANT.
    ClassSubject invariant = inspector.clazz(LIB_PKG + "Invariant");
    assertThat(invariant, isPresent());
    KmClassSubject kmClass = invariant.getKmClass();
    assertThat(kmClass, isPresent());
    assertEquals(2, kmClass.typeParameters().size());
    inspectTypeParameter(kmClass, "T", 0, FLAG_NONE, KmVariance.INVARIANT);
    inspectTypeParameter(kmClass, "C", 1, FLAG_NONE, KmVariance.INVARIANT);

    // Check that funGenerics method has a type-parameter with id = 2.
    KmFunctionSubject funGenerics = kmClass.kmFunctionWithUniqueName("funGenerics");
    assertThat(funGenerics, isPresent());
    assertEquals(1, funGenerics.typeParameters().size());
    inspectTypeParameter(funGenerics, "R", 2, FLAG_NONE, KmVariance.INVARIANT);
    assertEquals(1, funGenerics.valueParameters().size());
    KmValueParameterSubject kmValueParameterSubject = funGenerics.valueParameters().get(0);
    assertTrue(kmValueParameterSubject.type().classifier().isTypeParameter());
    TypeParameter typeParameter = kmValueParameterSubject.type().classifier().asTypeParameter();
    assertEquals(2, typeParameter.getId());

    // Check that the funGenerics method return type is referencing the method type parameter.
    KmTypeSubject funGenericsReturnType = funGenerics.returnType();
    assertTrue(funGenericsReturnType.classifier().isTypeParameter());
    assertEquals(2, funGenericsReturnType.classifier().asTypeParameter().getId());

    // Check funGenericsWithUpperBounds has an upperBound of SomeClass.
    KmFunctionSubject funGenericsWithUpperBounds =
        kmClass.kmFunctionWithUniqueName("funGenericsWithUpperBounds");
    assertThat(funGenericsWithUpperBounds, isPresent());
    assertEquals(1, funGenericsWithUpperBounds.typeParameters().size());
    inspectTypeParameter(funGenericsWithUpperBounds, "R", 2, FLAG_NONE, KmVariance.INVARIANT);
    KmTypeParameterSubject methodTypeParameter = funGenericsWithUpperBounds.typeParameters().get(0);
    List<KmTypeSubject> upperBounds = methodTypeParameter.upperBounds();
    assertEquals(2, upperBounds.size());
    assertThat(upperBounds.get(0), isDexClass(someClass.getDexProgramClass()));
    assertEquals(KT_COMPARABLE, upperBounds.get(1).descriptor());
    // Check that the upper bound has a type argument.
    assertEquals(1, upperBounds.get(1).typeArguments().size());
    assertThat(
        upperBounds.get(1).typeArguments().get(0).type(),
        isDexClass(someClass.getDexProgramClass()));
  }

  private void inspectCoVariant(CodeInspector inspector) {
    // Check that the type-parameter for CoVariant is marked as OUT.
    ClassSubject invariant = inspector.clazz(LIB_PKG + "CoVariant");
    assertThat(invariant, isPresent());
    KmClassSubject kmClass = invariant.getKmClass();
    assertThat(kmClass, isPresent());
    assertEquals(1, kmClass.typeParameters().size());
    inspectTypeParameter(kmClass, "T", 0, FLAG_NONE, KmVariance.OUT);
    // Check that the return type of the property CoVariant.t refers to the type parameter.
    assertEquals(1, kmClass.getProperties().size());
    KmPropertySubject t = kmClass.kmPropertyWithUniqueName("t");
    assertThat(t, isPresent());
    assertTrue(t.returnType().typeArguments().isEmpty());
    assertEquals(
        kmClass.typeParameters().get(0).getId(),
        t.returnType().classifier().asTypeParameter().getId());
  }

  private void inspectContraVariant(CodeInspector inspector) {
    // Check that the type-parameter for ContraVariant is marked as IN.
    ClassSubject invariant = inspector.clazz(LIB_PKG + "ContraVariant");
    assertThat(invariant, isPresent());
    KmClassSubject kmClass = invariant.getKmClass();
    assertThat(kmClass, isPresent());
    assertEquals(1, kmClass.typeParameters().size());
    inspectTypeParameter(kmClass, "T", 0, FLAG_NONE, KmVariance.IN);
  }

  private void inspectExtensions(CodeInspector inspector) {
    ClassSubject clazz = inspector.clazz(LIB_PKG + "LibKt");
    assertThat(clazz, isPresent());
    KmPackageSubject kmPackage = clazz.getKmPackage();
    assertThat(kmPackage, isPresent());
    KmFunctionSubject asListWithVarargs =
        kmPackage.kmFunctionExtensionWithUniqueName("asListWithVarargs");
    assertThat(asListWithVarargs, isExtensionFunction());
    inspectTypeParameter(asListWithVarargs, "T", 0, FLAG_REIFIED, KmVariance.INVARIANT);
    // Check that the varargs type argument has OUT invariance.
    List<KmTypeProjectionSubject> kmTypeProjectionSubjects =
        asListWithVarargs.returnType().typeArguments();
    assertEquals(1, kmTypeProjectionSubjects.size());
    KmTypeSubject type = kmTypeProjectionSubjects.get(0).type();
    assertEquals(1, type.typeArguments().size());
    KmTypeProjectionSubject kmTypeProjectionSubject = type.typeArguments().get(0);
    assertEquals(KmVariance.OUT, kmTypeProjectionSubject.variance());
  }

  private void inspectTypeParameter(
      KmTypeParameterSubjectMixin subject, String name, int id, int flags, KmVariance variance) {
    KmTypeParameterSubject typeParameter = subject.kmTypeParameterWithUniqueName(name);
    assertThat(typeParameter, isPresent());
    assertEquals(id, typeParameter.getId());
    assertEquals(flags, typeParameter.getFlags());
    assertEquals(variance, typeParameter.getVariance());
  }
}
