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

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

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.NoVerticalClassMerging;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.google.common.collect.Iterables;
import java.util.Objects;
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 ForwardingConstructorShakingOnDexWithClassMergingTest extends TestBase {

  @Parameter(0)
  public TestParameters parameters;

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

  @Test
  public void test() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(getClass())
        .addKeepMainRule(Main.class)
        .addOptionsModification(
            options ->
                options.testing.horizontalClassMergingTarget =
                    (appView, candidates, target) ->
                        Iterables.find(
                            candidates,
                            candidate -> candidate.getTypeName().equals(B.class.getTypeName())))
        .addHorizontallyMergedClassesInspector(
            inspector -> inspector.assertMergedInto(A.class, B.class).assertNoOtherClassesMerged())
        .enableInliningAnnotations()
        .enableNoVerticalClassMergingAnnotations()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .inspect(this::inspect)
        .run(parameters.getRuntime(), Main.class)
        .assertSuccessWithOutputLines("Hello, world!");
  }

  private void inspect(CodeInspector inspector) {
    ClassSubject aSubClassSubject = inspector.clazz(ASub.class);
    assertThat(aSubClassSubject, isPresent());
    assertEquals(
        parameters.canHaveNonReboundConstructorInvoke() ? 0 : 1,
        aSubClassSubject.allMethods().size());
  }

  public static class Main {

    public static void main(String[] args) {
      System.out.print(new A(obfuscate("Hello")).getMessageFromA());
      System.out.print(new ASub(obfuscate(", ")).getMessageFromA());
      System.out.println(new B(obfuscate("world!")).getMessageFromB());
    }

    @NeverInline
    private static String obfuscate(String str) {
      return System.currentTimeMillis() > 0 ? str : "dead";
    }

    @NeverInline
    public static void requireNonNull(Object o) {
      Objects.requireNonNull(o);
    }
  }

  @NoVerticalClassMerging
  public static class A {

    private final String msg;

    // Will be merged with B.<init>(String). Since B is chosen as the merge target, a new
    // B.<init>(String, int) method will be generated, and mappings will be created from
    // A.<init>(String) -> B.init$A(String) and B.<init>(String) -> B.init$B(String).
    public A(String msg) {
      // So that A.<init>(String) and B.<init>(String) will not be considered identical during class
      // merging. The indirection is to ensure that the API level of class A is 1.
      Main.requireNonNull(msg);
      this.msg = msg;
    }

    // Will be moved to B.<init>(String, String) by horizontal class merging, and then be optimized
    // to B.<init>(String) by unused argument removal.
    public A(String unused, String msg) {
      this.msg = msg;
    }

    @NeverInline
    public String getMessageFromA() {
      return msg;
    }
  }

  public static class ASub extends A {

    // After horizontal class merging and unused argument removal, this is rewritten to target
    // B.<init>(String). This constructor can therefore be eliminated by the redundant bridge
    // removal phase.
    public ASub(String msg) {
      super("<unused>", msg);
    }
  }

  public static class B {

    private final String msg;

    public B(String msg) {
      this.msg = msg;
    }

    @NeverInline
    public String getMessageFromB() {
      return msg;
    }
  }
}
