// 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.ToolHelper.getKotlinAnnotationJar;
import static com.android.tools.r8.ToolHelper.getKotlinReflectJar;
import static com.android.tools.r8.ToolHelper.getKotlinStdlibJar;
import static com.android.tools.r8.utils.codeinspector.Matchers.isDexClass;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndNotRenamed;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentAndRenamed;
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertTrue;
import static org.hamcrest.MatcherAssert.assertThat;

import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.kotlin.Kotlin.ClassClassifiers;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.DescriptorUtils;
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.KmClassifierSubject;
import com.android.tools.r8.utils.codeinspector.KmPackageSubject;
import com.android.tools.r8.utils.codeinspector.KmTypeAliasSubject;
import com.android.tools.r8.utils.codeinspector.KmTypeProjectionSubject;
import com.android.tools.r8.utils.codeinspector.KmTypeSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.nio.file.Path;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class MetadataRewriteInTypeAliasTest extends KotlinMetadataTestBase {
  private static final String EXPECTED =
      StringUtils.lines(
          "Impl::foo",
          "Program::foo",
          "true",
          "42",
          "42",
          "42",
          "42",
          "42",
          "42",
          "42",
          "true",
          "42",
          "1",
          "ClassWithCompanion::fooOnCompanion",
          "42",
          "42",
          "1",
          "Hello World!",
          "class com.android.tools.r8.kotlin.metadata.typealias_lib.Super");

  private final TestParameters parameters;

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

  public MetadataRewriteInTypeAliasTest(
      TestParameters parameters, KotlinTestParameters kotlinParameters) {
    super(kotlinParameters);
    this.parameters = parameters;
  }

  private static final KotlinCompileMemoizer typeAliasLibJarMap =
      getCompileMemoizer(
          getKotlinFileInTest(PKG_PREFIX + "/typealias_lib", "lib"),
          getKotlinFileInTest(PKG_PREFIX + "/typealias_lib", "lib_ext"));

  @Test
  public void smokeTest() throws Exception {
    Path libJar = typeAliasLibJarMap.getForConfiguration(kotlinc, targetVersion);

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

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

  @Test
  public void testMetadataInTypeAlias_renamed() throws Exception {
    String superTypeName = "com.android.tools.r8.kotlin.metadata.typealias_lib.Super";
    String renamedSuperTypeName = "com.android.tools.r8.kotlin.metadata.typealias_lib.FooBar";
    Path libJar =
        testForR8(parameters.getBackend())
            .addClasspathFiles(
                getKotlinStdlibJar(kotlinc),
                getKotlinReflectJar(kotlinc),
                getKotlinAnnotationJar(kotlinc))
            .addProgramFiles(typeAliasLibJarMap.getForConfiguration(kotlinc, targetVersion))
            // Keep non-private members of Impl
            .addKeepRules("-keep class **.Impl { !private *; }")
            // Keep but allow obfuscation of types.
            .addKeepRules("-keep,allowobfuscation class " + PKG + ".typealias_lib.** { *; }")
            .addKeepRules("-keepclassmembernames class " + PKG + ".typealias_lib.**" + " { *; }")
            // Keep the Companion class for ClassWithCompanionC.
            .addKeepRules("-keep class **.ClassWithCompanion$Companion { *; }")
            // Keep the inner class, otherwise it cannot be constructed.
            .addKeepRules("-keep class **.*Inner { *; }")
            // Keep LibKt that contains the type-aliases and utils.
            .addKeepRules("-keep class **.LibKt, **.Lib_extKt { *; }")
            // Keep the library test methods
            .addKeepRules("-keep class " + PKG + ".typealias_lib.*Tester { *; }")
            .addKeepRules("-keep class " + PKG + ".typealias_lib.*Tester$Companion { *; }")
            .addKeepRules("-keep class " + PKG + ".typealias_lib.SubTypeOfAlias { *; }")
            .addApplyMapping(superTypeName + " -> " + renamedSuperTypeName + ":")
            .addKeepAttributes(
                ProguardKeepAttributes.RUNTIME_VISIBLE_ANNOTATIONS,
                ProguardKeepAttributes.SIGNATURE,
                ProguardKeepAttributes.INNER_CLASSES,
                ProguardKeepAttributes.ENCLOSING_METHOD)
            .compile()
            .inspect(this::inspect)
            .writeToZip();

    Path appJar =
        kotlinc(parameters.getRuntime().asCf(), kotlinc, targetVersion)
            .addClasspathFiles(libJar)
            .addSourceFiles(getKotlinFileInTest(PKG_PREFIX + "/typealias_app", "main"))
            .compile();

    testForJvm()
        .addRunClasspathFiles(getKotlinStdlibJar(kotlinc), getKotlinReflectJar(kotlinc), libJar)
        .addClasspath(appJar)
        .run(parameters.getRuntime(), PKG + ".typealias_app.MainKt")
        .assertSuccessWithOutput(EXPECTED.replace(superTypeName, renamedSuperTypeName));
  }

  private void inspect(CodeInspector inspector) {
    inspectLib(inspector);
    inspectLibExt(inspector);
  }

  private void inspectLib(CodeInspector inspector) {
    String packageName = PKG + ".typealias_lib";
    String itfClassName = packageName + ".Itf";
    String libKtClassName = packageName + ".LibKt";

    ClassSubject itf = inspector.clazz(itfClassName);
    assertThat(itf, isPresentAndRenamed());

    ClassSubject libKt = inspector.clazz(libKtClassName);
    assertThat(libKt, isPresentAndNotRenamed());

    MethodSubject seq = libKt.uniqueMethodWithName("seq");
    assertThat(seq, isPresentAndNotRenamed());

    // API entry is kept, hence the presence of Metadata.
    KmPackageSubject kmPackage = libKt.getKmPackage();
    assertThat(kmPackage, isPresent());

    String arrayDescriptor =
        DescriptorUtils.getDescriptorFromKotlinClassifier(ClassClassifiers.arrayBinaryName);

    // Check that typealias myAliasedArray<T> = Array<T> exists.
    KmTypeAliasSubject myAliasedArray = kmPackage.kmTypeAliasWithUniqueName("myAliasedArray");
    assertThat(myAliasedArray, isPresent());
    assertEquals(arrayDescriptor, myAliasedArray.expandedType().descriptor());

    // Check that typealias API = Itf has been rewritten correctly.
    KmTypeAliasSubject api = kmPackage.kmTypeAliasWithUniqueName("API");
    assertThat(api, isPresent());
    assertThat(api.expandedType(), isDexClass(itf.getDexProgramClass()));
    assertThat(api.underlyingType(), isDexClass(itf.getDexProgramClass()));

    // Check that the type-alias APIs exist and that the expanded type is renamed.
    KmTypeAliasSubject apIs = kmPackage.kmTypeAliasWithUniqueName("APIs");
    assertThat(apIs, isPresent());
    assertEquals(arrayDescriptor, apIs.expandedType().descriptor());
    assertEquals(1, apIs.expandedType().typeArguments().size());
    KmTypeProjectionSubject expandedArgument = apIs.expandedType().typeArguments().get(0);
    assertThat(expandedArgument.type(), isDexClass(itf.getDexProgramClass()));

    assertEquals(myAliasedArray.descriptor(packageName), apIs.underlyingType().descriptor());
    assertEquals(1, apIs.underlyingType().typeArguments().size());
    KmTypeProjectionSubject underlyingArgument = apIs.underlyingType().typeArguments().get(0);
    KmTypeSubject type = underlyingArgument.type();
    assertNotNull(type);
    assertTrue(type.classifier().isTypeAlias());
    assertEquals(api.descriptor(packageName), type.descriptor());
  }

  private void inspectLibExt(CodeInspector inspector) {
    String packageName = PKG + ".typealias_lib";
    String libKtClassName = packageName + ".Lib_extKt";

    // Check that Arr has been renamed.
    ClassSubject arr = inspector.clazz(packageName + ".Arr");
    assertThat(arr, isPresentAndRenamed());

    ClassSubject libKt = inspector.clazz(libKtClassName);
    KmPackageSubject kmPackage = libKt.getKmPackage();

    // typealias Arr1D<K> = Arr<K>
    KmTypeAliasSubject arr1D = kmPackage.kmTypeAliasWithUniqueName("Arr1D");
    assertThat(arr1D, isPresent());
    assertThat(arr1D.expandedType(), isDexClass(arr.getDexProgramClass()));

    // typealias Arr2D<K> = Arr1D<Arr1D<K>>
    KmTypeAliasSubject arr2D = kmPackage.kmTypeAliasWithUniqueName("Arr2D");
    assertThat(arr2D, isPresent());
    assertThat(arr2D.expandedType(), isDexClass(arr.getDexProgramClass()));
    assertEquals(1, arr2D.expandedType().typeArguments().size());
    KmTypeProjectionSubject arr2DexpandedArg = arr2D.expandedType().typeArguments().get(0);
    assertThat(arr2DexpandedArg.type(), isDexClass(arr.getDexProgramClass()));

    assertEquals(arr1D.descriptor(packageName), arr2D.underlyingType().descriptor());
    assertEquals(1, arr2D.underlyingType().typeArguments().size());
    KmTypeProjectionSubject arr2DunderlyingArg = arr2D.underlyingType().typeArguments().get(0);
    assertEquals(arr1D.descriptor(packageName), arr2DunderlyingArg.type().descriptor());

    // typealias IntSet = Set<Int>
    // typealias MyMapToSetOfInt<K> = MutableMap<K, IntSet>
    KmTypeAliasSubject intSet = kmPackage.kmTypeAliasWithUniqueName("IntSet");
    assertThat(intSet, isPresent());

    KmTypeAliasSubject myMapToSetOfInt = kmPackage.kmTypeAliasWithUniqueName("MyMapToSetOfInt");
    assertThat(myMapToSetOfInt, isPresent());
    assertEquals(2, myMapToSetOfInt.underlyingType().typeArguments().size());
    assertEquals(2, myMapToSetOfInt.expandedType().typeArguments().size());
    assertEquals(1, myMapToSetOfInt.typeParameters().size());
    KmClassifierSubject typeClassifier =
        myMapToSetOfInt.underlyingType().typeArguments().get(0).type().classifier();
    assertTrue(typeClassifier.isTypeParameter());
    // Check that the type-variable K in 'MyMapToSetOfInt<K>' is the first argument in
    // MutableMap<K, IntSet>.
    assertEquals(
        myMapToSetOfInt.typeParameters().get(0).getId(), typeClassifier.asTypeParameter().getId());

    KmTypeSubject underlyingType = myMapToSetOfInt.underlyingType().typeArguments().get(1).type();
    assertEquals(intSet.descriptor(packageName), underlyingType.descriptor());

    KmTypeSubject expandedType = myMapToSetOfInt.expandedType().typeArguments().get(1).type();
    assertTrue(intSet.expandedType().equalUpToAbbreviatedType(expandedType));

    // Check that the following exist:
    // typealias MyHandler = (Int, Any) -> Unit
    // typealias MyGenericPredicate<T> = (T) -> Boolean
    assertThat(kmPackage.kmTypeAliasWithUniqueName("MyHandler"), isPresent());
    KmTypeAliasSubject genericPredicate = kmPackage.kmTypeAliasWithUniqueName("MyGenericPredicate");
    assertThat(genericPredicate, isPresent());

    // Check that the type-variable T in 'MyGenericPredicate<T>' is the input argument in
    // (T) -> Boolean.
    assertEquals(1, genericPredicate.typeParameters().size());
    assertEquals(2, genericPredicate.expandedType().typeArguments().size());
    KmTypeProjectionSubject kmTypeGenericArgumentSubject =
        genericPredicate.expandedType().typeArguments().get(0);
    assertTrue(kmTypeGenericArgumentSubject.type().classifier().isTypeParameter());
    assertEquals(
        genericPredicate.typeParameters().get(0).getId(),
        kmTypeGenericArgumentSubject.type().classifier().asTypeParameter().getId());

    // typealias ClassWithCompanionC = ClassWithCompanion.Companion
    KmTypeAliasSubject classWithCompanionC =
        kmPackage.kmTypeAliasWithUniqueName("ClassWithCompanionC");
    assertThat(classWithCompanionC, isPresent());

    ClassSubject companionClazz = inspector.clazz(packageName + ".ClassWithCompanion$Companion");
    assertThat(classWithCompanionC.expandedType(), isDexClass(companionClazz.getDexProgramClass()));
  }
}
