// Copyright (c) 2021, 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.ir.optimize.inliner;

import static org.junit.Assume.assumeFalse;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.R8TestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.transformers.ClassFileTransformer.MethodPredicate;
import com.android.tools.r8.utils.BooleanUtils;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

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

  @Parameter(0)
  public boolean enableInlining;

  @Parameter(1)
  public boolean enableVerticalClassMerging;

  @Parameter(2)
  public TestParameters parameters;

  @Parameters(name = "{2}, inlining: {0}, vertical class merging: {1}")
  public static List<Object[]> parameters() {
    return buildParameters(
        BooleanUtils.values(),
        BooleanUtils.values(),
        getTestParameters().withAllRuntimesAndApiLevels().build());
  }

  @Test
  public void testRuntime() throws Exception {
    assumeFalse(enableInlining);
    assumeFalse(enableVerticalClassMerging);
    testForRuntime(parameters)
        .addProgramClasses(I.class, J.class, A.class, B.class)
        .addProgramClassFileData(getTransformedMain())
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines("0", "0");
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addProgramClasses(I.class, J.class, A.class, B.class)
        .addProgramClassFileData(getTransformedMain())
        .addKeepMainRule(Main.class)
        // Keep getA() and getB() to prevent that we optimize it into having static return type A/B.
        .addKeepRules("-keepclassmembers class " + Main.class.getTypeName() + " { *** get?(...); }")
        .addInliningAnnotations()
        .addNoVerticalClassMergingAnnotations()
        .applyIf(!enableInlining, R8TestBuilder::enableInliningAnnotations)
        .applyIf(
            !enableVerticalClassMerging,
            testBuilder ->
                testBuilder
                    .addOptionsModification(
                        options ->
                            options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces())
                    .enableNoVerticalClassMergingAnnotations())
        .enableNoHorizontalClassMergingAnnotations()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines("0", "0");
  }

  private static byte[] getTransformedMain() throws IOException {
    return transformer(Main.class)
        .transformMethodInsnInMethod(
            "main",
            (opcode, owner, name, descriptor, isInterface, visitor) -> {
              if (name.startsWith("get")) {
                visitor.visitMethodInsn(opcode, owner, name, "(I)Ljava/lang/Object;", isInterface);
              } else {
                visitor.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
              }
            })
        .setReturnType(MethodPredicate.onName("getA"), Object.class.getTypeName())
        .setReturnType(MethodPredicate.onName("getB"), Object.class.getTypeName())
        .transform();
  }

  static class Main {

    public static void main(String[] args) {
      // Transformed from `I getA(int)` to `Object getA(int)` and `J getB(int)` to
      // `Object getB(int)`.
      test(getA(args.length), getB(args.length));
    }

    // @Keep
    static /*Object*/ I getA(int f) {
      return new A(f);
    }

    // @Keep
    static /*Object*/ J getB(int f) {
      return new B(f);
    }

    @NeverInline
    static void test(I i, J j) {
      i.m();
      j.m();
    }
  }

  @NoHorizontalClassMerging
  @NoVerticalClassMerging
  interface I {

    void m();
  }

  @NoHorizontalClassMerging
  static class A implements I {

    int f;

    A(int f) {
      this.f = f;
    }

    @Override
    public void m() {
      System.out.println(f);
    }
  }

  @NoHorizontalClassMerging
  @NoVerticalClassMerging
  interface J {

    void m();
  }

  @NoHorizontalClassMerging
  static class B implements J {

    int f;

    B(int f) {
      this.f = f;
    }

    @Override
    public void m() {
      System.out.println(f);
    }
  }
}
