// 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.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 KotlinLambdaMergingTrivialKotlinStyleTest 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 KotlinLambdaMergingTrivialKotlinStyleTest(
      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())
        .addDontWarnJetBrainsNotNullAnnotation()
        .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(0, lambdasInInput.getNumberOfJStyleLambdas());
    assertEquals(28, lambdasInInput.getNumberOfKStyleLambdas());

    if (!allowAccessModification) {
      // Only a subset of all K-style Kotlin lambdas are merged without -allowaccessmodification.
      Set<ClassReference> unmergedLambdas =
          ImmutableSet.of(
              lambdasInInput.getKStyleLambdaReferenceFromTypeName(
                  getTestName(), "inner.InnerKt$testInnerStateless$7"));
      inspector
          .assertClassReferencesMerged(
              lambdasInInput.getKStyleLambdas().stream()
                  .filter(not(unmergedLambdas::contains))
                  .collect(Collectors.toList()))
          .assertClassReferencesNotMerged(unmergedLambdas);
      return;
    }

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

  private String getExpectedOutput() {
    return StringUtils.lines(
        "first empty",
        "second empty",
        "first single",
        "second single",
        "third single",
        "caught: exception#14",
        "15",
        "16-17",
        "181920",
        "one-two-three",
        "one-two-...-twentythree",
        "46474849505152535455565758596061626364656667",
        "first empty",
        "second empty",
        "first single",
        "second single",
        "third single",
        "71",
        "72-73",
        "1",
        "5",
        "8",
        "20",
        "5",
        "",
        "kotlin.Unit",
        "10",
        "kotlin.Unit",
        "13",
        "kotlin.Unit",
        "14 -- 10",
        "kotlin.Unit");
  }

  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());
  }

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