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

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