// Copyright (c) 2020, 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.desugar;

import static com.android.tools.r8.ir.desugar.LambdaClass.JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX;
import static com.android.tools.r8.ir.desugar.LambdaClass.R8_LAMBDA_ACCESSOR_METHOD_PREFIX;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.FoundMethodSubject;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class DesugarInstanceLambdaWithReadsTest extends TestBase {

  static final String EXPECTED = StringUtils.lines("false");

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimes().withAllApiLevels().build();
  }

  public DesugarInstanceLambdaWithReadsTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  @Test
  public void testReference() throws Exception {
    testForRuntime(parameters)
        .addProgramClasses(Main.class, A.class, B.class, Consumer.class)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(inspector -> checkNumberOfLambdaMethods(inspector, false));
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(Main.class, A.class, B.class, Consumer.class)
        .addKeepClassRules(Consumer.class)
        .addKeepMainRule(Main.class)
        .enableInliningAnnotations()
        .setMinApi(parameters.getApiLevel())
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutput(EXPECTED)
        .inspect(inspector -> checkNumberOfLambdaMethods(inspector, true));
  }

  private void checkNumberOfLambdaMethods(CodeInspector inspector, boolean isR8) {
    // When generating DEX, only R8 synthesizes an accessor for the javac-generated lambda$ method.
    List<FoundMethodSubject> lambdaAccessorMethods =
        inspector
            .clazz(Main.class)
            .allMethods(m -> m.getOriginalName().startsWith(R8_LAMBDA_ACCESSOR_METHOD_PREFIX));
    assertEquals(
        BooleanUtils.intValue(parameters.isDexRuntime() && isR8), lambdaAccessorMethods.size());

    // When generating DEX, R8 will inline the javac-generated lambda$ method into the synthesized
    // $r8$lambda$ accessor method.
    List<FoundMethodSubject> lambdaImplementationMethods =
        inspector
            .clazz(Main.class)
            .allMethods(m -> m.getOriginalName().startsWith(JAVAC_EXPECTED_LAMBDA_METHOD_PREFIX));
    assertEquals(
        1 - BooleanUtils.intValue(parameters.isDexRuntime() && isR8),
        lambdaImplementationMethods.size());
  }

  private interface Consumer {
    void accept(String arg);
  }

  abstract static class A {
    abstract boolean contains(String item);
  }

  // A is expected to be merged into B.
  static class B extends A {
    final List<String> items;

    public B(List<String> items) {
      this.items = items;
    }

    @NeverInline
    @Override
    boolean contains(String item) {
      return items.contains(item);
    }
  }

  static class Main {
    // Field that is read from the lambda$ method (private ensures the method can't be inlined).
    private A filter;

    public Main(A filter) {
      this.filter = filter;
    }

    @NeverInline
    public static void forEach(List<String> args, Consumer fn) {
      for (String arg : args) {
        fn.accept(arg);
      }
    }

    public void foo(List<String> args) {
      forEach(args, arg -> System.out.println(filter.contains(arg)));
    }

    public static void main(String[] args) {
      new Main(new B(Arrays.asList(args))).foo(Collections.singletonList("hello!"));
    }
  }
}
