// 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.Sets;
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 KotlinLambdaMergingSingletonTest 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 KotlinLambdaMergingSingletonTest(
      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(parameters)
        .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)
        .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(2, lambdasInInput.getNumberOfJStyleLambdas());
    assertEquals(7, lambdasInInput.getNumberOfKStyleLambdas());

    // All J-style Kotlin lambdas should be merged into one class.
    inspector.assertIsCompleteMergeGroup(lambdasInInput.getJStyleLambdas());

    // A subset of the K-style Kotlin lambdas should be merged into one class.
    Set<ClassReference> kStyleLambdaMergeGroup =
        Sets.newHashSet(
            lambdasInInput.getKStyleLambdaReferenceFromTypeName(
                getTestName(), "MainKt$test2$$inlined$process$1"),
            lambdasInInput.getKStyleLambdaReferenceFromTypeName(
                getTestName(), "MainKt$test2$$inlined$process$2"),
            lambdasInInput.getKStyleLambdaReferenceFromTypeName(
                getTestName(), "MainKt$test2$$inlined$process$3"),
            lambdasInInput.getKStyleLambdaReferenceFromTypeName(
                getTestName(), "MainKt$test2$$inlined$process$4"));
    if (allowAccessModification) {
      kStyleLambdaMergeGroup.add(
          lambdasInInput.getKStyleLambdaReferenceFromTypeName(
              getTestName(), "MainKt$test2$lambda$1"));
    }
    inspector.assertIsCompleteMergeGroup(kStyleLambdaMergeGroup);

    // The remaining lambdas are not merged.
    inspector.assertClassReferencesNotMerged(
        lambdasInInput.getAllLambdas().stream()
            .filter(not(lambdasInInput::isJStyleLambda))
            .filter(not(kStyleLambdaMergeGroup::contains))
            .collect(Collectors.toSet()));
  }

  private String getExpectedOutput() {
    return StringUtils.lines(
        "(*000*001*002*003*004*005*006*007*008*009*)",
        "(*000*001*002*003*004*005*006*007*008*009*)",
        "(*010*011*)",
        "(*012*013*014*)",
        "(*015*016*)",
        "(*017*018*019*)");
  }

  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(), kotlinc.getKotlinAnnotationJar());
  }

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