// 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.getKotlinCompilers;
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.KotlinCompilerTool.KotlinCompiler;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
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}, target: {1}, kotlinc: {2}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters().withCfRuntimes().build(),
        KotlinTargetVersion.values(),
        getKotlinCompilers());
  }

  public MetadataRewriteInTypeAliasTest(
      TestParameters parameters, KotlinTargetVersion targetVersion, KotlinCompiler kotlinc) {
    super(targetVersion, kotlinc);
    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(
            ToolHelper.getKotlinStdlibJar(kotlinc), ToolHelper.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(
                ToolHelper.getKotlinStdlibJar(kotlinc), ToolHelper.getKotlinReflectJar(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)
            .addDontWarnJetBrainsNotNullAnnotation()
            .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(
            ToolHelper.getKotlinStdlibJar(kotlinc), ToolHelper.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()));
  }
}
