// Copyright (c) 2018, 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;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.ToolHelper.KotlinTargetVersion;
import com.android.tools.r8.code.NewInstance;
import com.android.tools.r8.code.SgetObject;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
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.InstructionSubject;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;

public class KotlinClassInlinerTest extends AbstractR8KotlinTestBase {

  public KotlinClassInlinerTest(
      KotlinTargetVersion targetVersion, boolean allowAccessModification) {
    super(targetVersion, allowAccessModification);
  }

  private static boolean isLambda(DexClass clazz) {
    return !clazz.type.getPackageDescriptor().startsWith("kotlin") &&
        (isKStyleLambdaOrGroup(clazz) || isJStyleLambdaOrGroup(clazz));
  }

  private static boolean isKStyleLambdaOrGroup(DexClass clazz) {
    return clazz.superType.descriptor.toString().equals("Lkotlin/jvm/internal/Lambda;");
  }

  private static boolean isJStyleLambdaOrGroup(DexClass clazz) {
    return clazz.superType.descriptor.toString().equals("Ljava/lang/Object;") &&
        clazz.interfaces.size() == 1;
  }

  private static Predicate<DexType> createLambdaCheck(CodeInspector inspector) {
    Set<DexType> lambdaClasses = inspector.allClasses().stream()
        .filter(clazz -> isLambda(clazz.getDexClass()))
        .map(clazz -> clazz.getDexClass().type)
        .collect(Collectors.toSet());
    return lambdaClasses::contains;
  }

  @Test
  public void testJStyleLambdas() throws Exception {
    assumeTrue("Only work with -allowaccessmodification", allowAccessModification);
    final String mainClassName = "class_inliner_lambda_j_style.MainKt";
    runTest("class_inliner_lambda_j_style", mainClassName, false, (app) -> {
      CodeInspector inspector = new CodeInspector(app);
      assertTrue(
          inspector.clazz("class_inliner_lambda_j_style.MainKt$testStateful$1").isPresent());
      assertTrue(
          inspector.clazz("class_inliner_lambda_j_style.MainKt$testStateful2$1").isPresent());
      assertTrue(
          inspector.clazz("class_inliner_lambda_j_style.MainKt$testStateful3$1").isPresent());
    });

    runTest("class_inliner_lambda_j_style", mainClassName, true, (app) -> {
      CodeInspector inspector = new CodeInspector(app);
      Predicate<DexType> lambdaCheck = createLambdaCheck(inspector);
      ClassSubject clazz = inspector.clazz(mainClassName);

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz, "testStateless"));

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz, "testStateful"));

      assertFalse(
          inspector.clazz("class_inliner_lambda_j_style.MainKt$testStateful$1").isPresent());

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz, "testStateful2"));

      assertFalse(
          inspector.clazz("class_inliner_lambda_j_style.MainKt$testStateful2$1").isPresent());

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz, "testStateful3"));

      assertFalse(
          inspector.clazz("class_inliner_lambda_j_style.MainKt$testStateful3$1").isPresent());
    });
  }

  @Test
  public void testKStyleLambdas() throws Exception {
    assumeTrue("Only work with -allowaccessmodification", allowAccessModification);
    final String mainClassName = "class_inliner_lambda_k_style.MainKt";
    runTest("class_inliner_lambda_k_style", mainClassName, false, (app) -> {
      CodeInspector inspector = new CodeInspector(app);
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testKotlinSequencesStateless$1").isPresent());
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testKotlinSequencesStateful$1").isPresent());
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethod$1").isPresent());
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethod2$1").isPresent());
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethod3$1").isPresent());
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethodReturningLambda$1")
          .isPresent());
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethodReturningLambda2$1")
          .isPresent());
      assertTrue(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethodReturningLambda3$1")
          .isPresent());
    });

    runTest("class_inliner_lambda_k_style", mainClassName, true, (app) -> {
      CodeInspector inspector = new CodeInspector(app);
      Predicate<DexType> lambdaCheck = createLambdaCheck(inspector);
      ClassSubject clazz = inspector.clazz(mainClassName);

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz,
              "testKotlinSequencesStateless", "kotlin.sequences.Sequence"));

      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testKotlinSequencesStateless$1").isPresent());

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz,
              "testKotlinSequencesStateful", "int", "int", "kotlin.sequences.Sequence"));

      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testKotlinSequencesStateful$1").isPresent());

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz, "testBigExtraMethod"));

      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethod$1").isPresent());
      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethod2$1").isPresent());
      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethod3$1").isPresent());

      assertEquals(
          Sets.newHashSet(),
          collectAccessedTypes(lambdaCheck, clazz, "testBigExtraMethodReturningLambda"));

      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethodReturningLambda$1")
          .isPresent());
      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethodReturningLambda2$1")
          .isPresent());
      assertFalse(inspector.clazz(
          "class_inliner_lambda_k_style.MainKt$testBigExtraMethodReturningLambda3$1")
          .isPresent());
    });
  }

  @Test
  public void testDataClass() throws Exception {
    assumeTrue("Only work with -allowaccessmodification", allowAccessModification);
    final String mainClassName = "class_inliner_data_class.MainKt";
    runTest("class_inliner_data_class", mainClassName, true, (app) -> {
      CodeInspector inspector = new CodeInspector(app);
      ClassSubject clazz = inspector.clazz(mainClassName);
      assertTrue(collectAccessedTypes(
          type -> !type.toSourceString().startsWith("java."),
          clazz, "main", String[].class.getCanonicalName()).isEmpty());
      assertEquals(
          Lists.newArrayList(
              "void kotlin.jvm.internal.Intrinsics.throwParameterIsNullException(java.lang.String)"
          ),
          collectStaticCalls(clazz, "main", String[].class.getCanonicalName()));
    });
  }

  private Set<String> collectAccessedTypes(Predicate<DexType> isTypeOfInterest,
      ClassSubject clazz, String methodName, String... params) {
    assertNotNull(clazz);
    MethodSignature signature = new MethodSignature(methodName, "void", params);
    DexCode code = clazz.method(signature).getMethod().getCode().asDexCode();
    return Stream.concat(
        filterInstructionKind(code, NewInstance.class)
            .map(insn -> ((NewInstance) insn).getType()),
        filterInstructionKind(code, SgetObject.class)
            .map(insn -> insn.getField().holder)
    )
        .filter(isTypeOfInterest)
        .map(DexType::toSourceString)
        .collect(Collectors.toSet());
  }

  protected void runTest(String folder, String mainClass,
      boolean enabled, AndroidAppInspector inspector) throws Exception {
    runTest(
        folder, mainClass,
        // TODO(jsjeon): Introduce @NeverInline to kotlinR8TestResources
        StringUtils.lines(
            "-neverinline class * { void test*State*(...); }",
            "-neverinline class * { void testBigExtraMethod(...); }",
            "-neverinline class * { void testBigExtraMethodReturningLambda(...); }"
        ),
        options -> {
          options.enableInlining = true;
          options.enableClassInlining = enabled;
          options.enableLambdaMerging = false;
          // Tests check if specific lambdas are inlined or not, where some of target lambdas have
          // at least 4 instructions.
          options.inliningInstructionLimit = 4;
        }, inspector);
  }

  private List<String> collectStaticCalls(ClassSubject clazz, String methodName, String... params) {
    assertNotNull(clazz);
    MethodSignature signature = new MethodSignature(methodName, "void", params);
    MethodSubject method = clazz.method(signature);
    return Streams.stream(method.iterateInstructions(InstructionSubject::isInvokeStatic))
        .map(insn -> insn.getMethod().toSourceString())
        .sorted()
        .collect(Collectors.toList());
  }
}
