// 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.ir.optimize.uninstantiatedtypes;

import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoHorizontalClassMerging;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
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 ParameterRewritingTest extends TestBase {

  private final TestParameters parameters;

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

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

  @Test
  public void test() throws Exception {
    String expected =
        StringUtils.lines(
            "Factory.createStatic() -> null",
            "Factory.createStaticWithUnused1() -> null",
            "Factory.createStaticWithUnused2() -> null",
            "Factory.createStaticWithUnused3() -> null",
            "Factory.createStaticWithUnused4() -> null");

    testForJvm().addTestClasspath().run(TestClass.class).assertSuccessWithOutput(expected);

    CodeInspector inspector =
        testForR8(parameters.getBackend())
            .addInnerClasses(ParameterRewritingTest.class)
            .addKeepMainRule(TestClass.class)
            .enableInliningAnnotations()
            .enableNoHorizontalClassMergingAnnotations()
            .addOptionsModification(options -> options.enableClassInlining = false)
            .addDontObfuscate()
            .setMinApi(parameters.getApiLevel())
            .run(parameters.getRuntime(), TestClass.class)
            .assertSuccessWithOutput(expected)
            .inspector();

    ClassSubject factoryClassSubject = inspector.clazz(Factory.class);
    MethodSubject createStaticMethodSubject =
        factoryClassSubject.uniqueMethodWithName("createStatic");
    assertThat(createStaticMethodSubject, isPresent());
    assertEquals(1, createStaticMethodSubject.getMethod().getParameters().size());

    for (int i = 1; i <= 3; ++i) {
      String createStaticWithUnusedMethodName = "createStaticWithUnused" + i;
      MethodSubject createStaticWithUnusedMethodSubject =
          factoryClassSubject.uniqueMethodWithName(createStaticWithUnusedMethodName);
      assertThat(createStaticWithUnusedMethodSubject, isPresent());

      DexMethod method = createStaticWithUnusedMethodSubject.getMethod().getReference();
      assertEquals(1, method.getParameters().size());
      assertEquals("java.lang.String", method.getParameters().toString());
    }

    MethodSubject createStaticWithUnusedMethodSubject =
        factoryClassSubject.uniqueMethodWithName("createStaticWithUnused4");
    assertThat(createStaticWithUnusedMethodSubject, isPresent());

    DexMethod method = createStaticWithUnusedMethodSubject.getMethod().getReference();
    assertEquals(3, method.getParameters().size());
    assertEquals(
        "java.lang.String java.lang.String java.lang.String", method.getParameters().toString());

    assertThat(inspector.clazz(Uninstantiated.class), not(isPresent()));
  }

  static class TestClass {

    public static void main(String[] args) {
      Object obj1 = Factory.createStatic(null, asNonConstantString("Factory.createStatic()"));
      System.out.println(" -> " + obj1);

      Object obj2 =
          Factory.createStaticWithUnused1(
              new Object(), null, asNonConstantString("Factory.createStaticWithUnused1()"));
      System.out.println(" -> " + obj2);

      Object obj3 =
          Factory.createStaticWithUnused2(
              null, new Object(), asNonConstantString("Factory.createStaticWithUnused2()"));
      System.out.println(" -> " + obj3);

      Object obj4 =
          Factory.createStaticWithUnused3(
              null, asNonConstantString("Factory.createStaticWithUnused3()"), new Object());
      System.out.println(" -> " + obj4);

      Object obj5 =
          Factory.createStaticWithUnused4(
              asNonConstantString("Factory"),
              new Object(),
              null,
              asNonConstantString("."),
              new Object(),
              null,
              asNonConstantString("createStaticWithUnused4()"));
      System.out.println(" -> " + obj5);
    }

    public static String asNonConstantString(String string) {
      return System.currentTimeMillis() > 0 ? string : null;
    }
  }

  @NoHorizontalClassMerging
  static class Uninstantiated {}

  @NoHorizontalClassMerging
  static class Factory {

    @NeverInline
    public static Object createStatic(Uninstantiated uninstantiated, String msg) {
      System.out.print(msg);
      return uninstantiated;
    }

    @NeverInline
    public static Object createStaticWithUnused1(
        Object unused, Uninstantiated uninstantiated, String msg) {
      System.out.print(msg);
      return uninstantiated;
    }

    @NeverInline
    public static Object createStaticWithUnused2(
        Uninstantiated uninstantiated, Object unused, String msg) {
      System.out.print(msg);
      return uninstantiated;
    }

    @NeverInline
    public static Object createStaticWithUnused3(
        Uninstantiated uninstantiated, String msg, Object unused) {
      System.out.print(msg);
      return uninstantiated;
    }

    @NeverInline
    public static Object createStaticWithUnused4(
        String msg1,
        Object unused1,
        Uninstantiated uninstantiated1,
        String msg2,
        Object unused2,
        Uninstantiated uninstantiated2,
        String msg3) {
      System.out.print(msg1 + msg2 + msg3);
      return oneOf(uninstantiated1, uninstantiated2);
    }

    @NeverInline
    private static <T> T oneOf(T x, T y) {
      return System.currentTimeMillis() > 0 ? x : y;
    }
  }
}
