// 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.lambda;

import static com.android.tools.r8.ToolHelper.getKotlinAnnotationJar;
import static com.android.tools.r8.utils.PredicateUtils.not;
import static junit.framework.TestCase.assertEquals;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.KotlinTestBase;
import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.HorizontallyMergedClassesInspector;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class KotlinLambdaMergingTrivialJavaStyleTest extends KotlinTestBase {

  private final boolean allowAccessModification;
  private final TestParameters parameters;

  @Parameters(name = "{0}, {1}, allow access modification: {2}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters()
            .withCfRuntime(CfVm.last())
            .withDexRuntime(Version.last())
            .withAllApiLevels()
            .build(),
        getKotlinTestParameters().withAllCompilersAndTargetVersions().build(),
        BooleanUtils.values());
  }

  public KotlinLambdaMergingTrivialJavaStyleTest(
      TestParameters parameters,
      KotlinTestParameters kotlinParameters,
      boolean allowAccessModification) {
    super(kotlinParameters);
    this.allowAccessModification = allowAccessModification;
    this.parameters = parameters;
  }

  @Test
  public void testJVM() throws Exception {
    assumeFalse(allowAccessModification);
    assumeTrue(parameters.isCfRuntime());
    assumeTrue(kotlinParameters.isFirst());
    testForJvm()
        .addProgramFiles(getProgramFiles())
        .run(parameters.getRuntime(), getMainClassName())
        .assertSuccessWithOutput(getExpectedOutput());
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramFiles(getProgramFiles())
        .addKeepMainRule(getMainClassName())
        .addHorizontallyMergedClassesInspector(this::inspect)
        .allowAccessModification(allowAccessModification)
        .allowDiagnosticWarningMessages()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .assertAllWarningMessagesMatch(
            containsString("Resource 'META-INF/MANIFEST.MF' already exists."))
        .run(parameters.getRuntime(), getMainClassName())
        .assertSuccessWithOutput(getExpectedOutput());
  }

  private void inspect(HorizontallyMergedClassesInspector inspector) throws IOException {
    // Get the Kotlin lambdas in the input.
    KotlinLambdasInInput lambdasInInput =
        KotlinLambdasInInput.create(getProgramFiles(), getTestName());
    assertEquals(39, lambdasInInput.getNumberOfJStyleLambdas());
    assertEquals(0, lambdasInInput.getNumberOfKStyleLambdas());

    if (!allowAccessModification) {
      // Only a subset of all J-style Kotlin lambdas are merged without -allowaccessmodification.
      Set<ClassReference> unmergedLambdas =
          ImmutableSet.of(
              lambdasInInput.getJStyleLambdaReferenceFromTypeName(
                  getTestName(), "inner.InnerKt$testInner1$1"),
              lambdasInInput.getJStyleLambdaReferenceFromTypeName(
                  getTestName(), "inner.InnerKt$testInner1$2"),
              lambdasInInput.getJStyleLambdaReferenceFromTypeName(
                  getTestName(), "inner.InnerKt$testInner1$3"),
              lambdasInInput.getJStyleLambdaReferenceFromTypeName(
                  getTestName(), "inner.InnerKt$testInner1$4"),
              lambdasInInput.getJStyleLambdaReferenceFromTypeName(
                  getTestName(), "inner.InnerKt$testInner1$5"));
      inspector
          .assertClassReferencesMerged(
              lambdasInInput.getJStyleLambdas().stream()
                  .filter(not(unmergedLambdas::contains))
                  .collect(Collectors.toList()))
          .assertClassReferencesNotMerged(unmergedLambdas);
      return;
    }

    // All J-style Kotlin lambdas are merged with -allowaccessmodification.
    inspector.assertClassReferencesMerged(lambdasInInput.getJStyleLambdas());
  }

  private String getExpectedOutput() {
    return StringUtils.lines(
        "{005:4}",
        "{007:6}",
        "009:{008}:{0}",
        "011:{010}:{0}",
        "013:{012}:{0}:{1}",
        "015:{014}:{0}:{1}",
        "017:{Local(id=016)}:{0}:{1}:{2}",
        "019:{Local(id=018)}:{0}:{1}:{2}",
        "021:{Local(id=Local(id=020))}:{0}:{1}:{2}:{3}",
        "023:{Local(id=Local(id=022))}:{0}:{1}:{2}:{3}",
        "27",
        "kotlin.Unit",
        "28",
        "kotlin.Unit",
        "029:024",
        "kotlin.Unit",
        "030:024",
        "kotlin.Unit",
        "031:024",
        "kotlin.Unit",
        "032:024",
        "kotlin.Unit",
        "Local(id=033):024:025",
        "kotlin.Unit",
        "Local(id=034):024:025",
        "kotlin.Unit",
        "Local(id=Local(id=035)):024:025:026",
        "kotlin.Unit",
        "Local(id=Local(id=036)):024:025:026",
        "kotlin.Unit",
        "037:038:039",
        "039:037:038",
        "038:039:037",
        "Local(id=037):038:039",
        "Local(id=038):037:039",
        "037:Local(id=038):039",
        "037:Local(id=039):038",
        "Local(id=Local(id=037)):Local(id=Local(id=038)):Local(id=Local(id=039))",
        "Local(id=Local(id=039)):Local(id=Local(id=037)):Local(id=Local(id=038))",
        "040:Local(id=041):Local(id=Local(id=042))",
        "Local(id=Local(id=042)):040:Local(id=041)",
        "Local(id=041):Local(id=Local(id=042)):040",
        "Local(id=040):Local(id=041):Local(id=Local(id=042))",
        "Local(id=Local(id=041)):040:Local(id=Local(id=042))",
        "040:Local(id=Local(id=041)):Local(id=Local(id=042))",
        "040:Local(id=Local(id=Local(id=042))):Local(id=041)",
        "Local(id=Local(id=040)):Local(id=Local(id=Local(id=041))):Local(id=Local(id=Local(id=Local(id=042))))",
        "Local(id=Local(id=Local(id=Local(id=042)))):Local(id=Local(id=040)):Local(id=Local(id=Local(id=041)))",
        "043:044:045",
        "045:043:044",
        "044:045:043",
        "Local(id=043):044:045",
        "Local(id=044):043:045",
        "046:Local(id=047):Local(id=048)",
        "Local(id=048):046:Local(id=047)",
        "Local(id=047):Local(id=048):046",
        "Local(id=046):Local(id=047):Local(id=048)",
        "Local(id=Local(id=047)):046:Local(id=048)",
        "{053:100}",
        "055:{054}:{49}",
        "057:{056}:{49}:{50}",
        "059:{InnerLocal(id=058)}:{49}:{50}:{51}",
        "061:{InnerLocal(id=InnerLocal(id=060))}:{49}:{50}:{51}:{52");
  }

  private Path getJavaJarFile() {
    return getJavaJarFile(getTestName());
  }

  private String getMainClassName() {
    return getTestName() + ".MainKt";
  }

  private List<Path> getProgramFiles() {
    Path kotlinJarFile =
        getCompileMemoizer(getKotlinFilesInResource(getTestName()), getTestName())
            .configure(kotlinCompilerTool -> kotlinCompilerTool.includeRuntime().noReflect())
            .getForConfiguration(kotlinc, targetVersion);
    return ImmutableList.of(kotlinJarFile, getJavaJarFile(), getKotlinAnnotationJar(kotlinc));
  }

  private String getTestName() {
    return "lambdas_jstyle_trivial";
  }
}
