// Copyright (c) 2023, 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 twr.twrcloseresourceduplication;

import static com.android.tools.r8.desugar.LibraryFilesHelper.getJdk11LibraryFiles;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static com.android.tools.r8.utils.codeinspector.Matchers.isPresentIf;
import static com.android.tools.r8.utils.codeinspector.Matchers.notIf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;

import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.profile.art.model.ExternalArtProfile;
import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.InlinerOptions;
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 com.google.common.collect.ImmutableList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class TwrCloseResourceDuplicationProfileRewritingTest
    extends TwrCloseResourceDuplicationTest {

  @Test
  public void testD8ProfileRewriting() throws Exception {
    testForD8(parameters.getBackend())
        .addProgramClassFileData(TwrCloseResourceDuplicationTest.getProgramInputs())
        .addArtProfileForRewriting(getArtProfile())
        .addOptionsModification(options -> options.testing.enableSyntheticSharing = false)
        .applyIf(
            parameters.isCfRuntime(),
            testBuilder ->
                testBuilder
                    .addLibraryFiles(getJdk11LibraryFiles(temp))
                    .addDefaultRuntimeLibrary(parameters),
            testBuilder ->
                testBuilder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.LATEST)))
        .collectSyntheticItems()
        .noHorizontalClassMergingOfSynthetics()
        .setMinApi(parameters)
        .compile()
        .apply(
            cr ->
                cr.inspectResidualArtProfile(
                    (profileInspector, inspector) ->
                        inspectD8(profileInspector, inspector, cr.getSyntheticItems())))
        .run(parameters.getRuntime(), MAIN, getZipFile())
        .assertSuccessWithOutput(TwrCloseResourceDuplicationTest.EXPECTED);
  }

  @Test
  public void testR8ProfileRewriting() throws Exception {
    parameters.assumeR8TestParameters();
    testForR8(parameters.getBackend())
        .addProgramClassFileData(TwrCloseResourceDuplicationTest.getProgramInputs())
        .addKeepMainRule(MAIN)
        .addKeepClassAndMembersRules(FOO, BAR)
        .addArtProfileForRewriting(getArtProfile())
        .addOptionsModification(InlinerOptions::disableInlining)
        .addOptionsModification(options -> options.testing.enableSyntheticSharing = false)
        .applyIf(
            parameters.isCfRuntime(),
            testBuilder ->
                testBuilder
                    .addLibraryFiles(getJdk11LibraryFiles(temp))
                    .addDefaultRuntimeLibrary(parameters)
                    .addOptionsModification(
                        options ->
                            options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces()),
            testBuilder ->
                testBuilder.addLibraryFiles(ToolHelper.getAndroidJar(AndroidApiLevel.LATEST)))
        .collectSyntheticItems()
        .noHorizontalClassMergingOfSynthetics()
        .setMinApi(parameters)
        .compile()
        .apply(
            cr ->
                cr.inspectResidualArtProfile(
                    (profileInspector, inspector) ->
                        inspectR8(profileInspector, inspector, cr.getSyntheticItems())))
        .run(parameters.getRuntime(), MAIN, getZipFile())
        .assertSuccessWithOutput(TwrCloseResourceDuplicationTest.EXPECTED);
  }

  private ExternalArtProfile getArtProfile() {
    List<TypeReference> closeResourceFormalParameters =
        ImmutableList.of(
            Reference.classFromClass(Throwable.class),
            Reference.classFromClass(AutoCloseable.class));
    return ExternalArtProfile.builder()
        .addMethodRule(
            Reference.method(
                Reference.classFromTypeName(FOO),
                "foo",
                ImmutableList.of(Reference.classFromClass(String.class)),
                null))
        .addMethodRule(
            // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
            Reference.method(
                Reference.classFromTypeName(FOO),
                "$closeResource",
                closeResourceFormalParameters,
                null))
        .addMethodRule(
            Reference.method(
                Reference.classFromTypeName(BAR),
                "bar",
                ImmutableList.of(Reference.classFromClass(String.class)),
                null))
        .addMethodRule(
            // NOTE: The $closeResource helper is _only_ generated by the JDK-9 compiler.
            Reference.method(
                Reference.classFromTypeName(BAR),
                "$closeResource",
                closeResourceFormalParameters,
                null))
        .build();
  }

  private void inspectD8(
      ArtProfileInspector profileInspector,
      CodeInspector inspector,
      SyntheticItemsTestUtils syntheticItems) {
    inspect(profileInspector, inspector, hasTwrCloseResourceSupport(true), syntheticItems);
  }

  private void inspectR8(
      ArtProfileInspector profileInspector,
      CodeInspector inspector,
      SyntheticItemsTestUtils syntheticItems) {
    inspect(
        profileInspector,
        inspector,
        hasTwrCloseResourceSupport(parameters.isDexRuntime()),
        syntheticItems);
  }

  private void inspect(
      ArtProfileInspector profileInspector,
      CodeInspector inspector,
      boolean hasTwrCloseResourceSupport,
      SyntheticItemsTestUtils syntheticItems) {
    int expectedClassCount = 3;
    if (!hasTwrCloseResourceSupport) {
      expectedClassCount += 8;
    }
    if (hasTwrCloseResourceApiOutlines()) {
      expectedClassCount += 4;
    }
    InternalOptions options = inspector.getApplication().options;
    options.setMinApiLevel(parameters.getApiLevel());
    if (options.shouldDesugarAutoCloseable()) {
      expectedClassCount += 12;
    }
    inspector
        .allClasses()
        .forEach(c -> System.out.println(c.getDexProgramClass().toSourceString()));
    assertEquals(expectedClassCount, inspector.allClasses().size());
    assertThat(inspector.clazz(MAIN), isPresent());

    // Class Foo has two methods foo() and $closeResource().
    ClassSubject fooClassSubject = inspector.clazz(FOO);
    assertThat(fooClassSubject, isPresent());

    MethodSubject fooMethodSubject = fooClassSubject.uniqueMethodWithOriginalName("foo");
    assertThat(fooMethodSubject, isPresent());

    MethodSubject fooCloseResourceMethodSubject =
        fooClassSubject.uniqueMethodWithOriginalName("$closeResource");
    assertThat(fooCloseResourceMethodSubject, isPresent());

    // Class Bar has two methods bar() and $closeResource().
    ClassSubject barClassSubject = inspector.clazz(BAR);
    assertThat(barClassSubject, isPresent());

    MethodSubject barMethodSubject = barClassSubject.uniqueMethodWithOriginalName("bar");
    assertThat(barMethodSubject, isPresent());

    MethodSubject barCloseResourceMethodSubject =
        barClassSubject.uniqueMethodWithOriginalName("$closeResource");
    assertThat(barCloseResourceMethodSubject, isPresent());

    profileInspector
        .assertContainsClassRules(fooClassSubject, barClassSubject)
        .assertContainsMethodRules(
            fooMethodSubject,
            fooCloseResourceMethodSubject,
            barMethodSubject,
            barCloseResourceMethodSubject);

    // There is 1 backport, 2 synthetic API outlines, and 3 twr classes for both Foo and Bar.
    for (String clazz : ImmutableList.of(FOO, BAR)) {
      ClassSubject syntheticApiOutlineClassSubject0 =
          inspector.syntheticClass(
              syntheticItems.syntheticApiOutlineClass(Reference.classFromTypeName(clazz), 0));
      assertThat(syntheticApiOutlineClassSubject0, isPresentIf(hasTwrCloseResourceApiOutlines()));

      ClassSubject syntheticApiOutlineClassSubject1 =
          inspector.syntheticClass(
              syntheticItems.syntheticApiOutlineClass(Reference.classFromTypeName(clazz), 1));
      assertThat(syntheticApiOutlineClassSubject1, isPresentIf(hasTwrCloseResourceApiOutlines()));

      int initialSyntheticId = hasTwrCloseResourceApiOutlines() ? 2 : 0;

      ClassSubject syntheticBackportClassSubject =
          inspector.syntheticClass(
              syntheticItems.syntheticBackportClass(
                  Reference.classFromTypeName(clazz), initialSyntheticId));
      assertThat(syntheticBackportClassSubject, notIf(isPresent(), hasTwrCloseResourceSupport));

      ClassSubject syntheticTwrCloseResourceClassSubject3 =
          inspector.syntheticClass(
              syntheticItems.syntheticTwrCloseResourceClass(
                  Reference.classFromTypeName(clazz), initialSyntheticId + 1));
      assertThat(
          syntheticTwrCloseResourceClassSubject3, notIf(isPresent(), hasTwrCloseResourceSupport));

      ClassSubject syntheticTwrCloseResourceClassSubject4 =
          inspector.syntheticClass(
              syntheticItems.syntheticTwrCloseResourceClass(
                  Reference.classFromTypeName(clazz), initialSyntheticId + 2));
      assertThat(
          syntheticTwrCloseResourceClassSubject4, notIf(isPresent(), hasTwrCloseResourceSupport));

      ClassSubject syntheticTwrCloseResourceClassSubject5 =
          inspector.syntheticClass(
              syntheticItems.syntheticTwrCloseResourceClass(
                  Reference.classFromTypeName(clazz), initialSyntheticId + 3));
      assertThat(
          syntheticTwrCloseResourceClassSubject5, notIf(isPresent(), hasTwrCloseResourceSupport));

      profileInspector.applyIf(
          hasTwrCloseResourceApiOutlines(),
          i ->
              i.assertContainsClassRules(
                      syntheticApiOutlineClassSubject0, syntheticApiOutlineClassSubject1)
                  .assertContainsMethodRules(
                      syntheticApiOutlineClassSubject0.uniqueMethod(),
                      syntheticApiOutlineClassSubject1.uniqueMethod()));

      profileInspector.applyIf(
          !hasTwrCloseResourceSupport,
          i ->
              i.assertContainsClassRules(
                      syntheticBackportClassSubject,
                      syntheticTwrCloseResourceClassSubject3,
                      syntheticTwrCloseResourceClassSubject4,
                      syntheticTwrCloseResourceClassSubject5)
                  .assertContainsMethodRules(
                      syntheticBackportClassSubject.uniqueMethod(),
                      syntheticTwrCloseResourceClassSubject3.uniqueMethod(),
                      syntheticTwrCloseResourceClassSubject4.uniqueMethod(),
                      syntheticTwrCloseResourceClassSubject5.uniqueMethod()));
    }

    profileInspector.applyIf(
        options.shouldDesugarAutoCloseable(),
        i ->
            i.assertContainsClassRules(
                    getCloseDispatcherSyntheticClasses(inspector, syntheticItems))
                .assertContainsMethodRules(
                    Arrays.stream(getCloseDispatcherSyntheticClasses(inspector, syntheticItems))
                        .map(ClassSubject::uniqueMethod)
                        .toArray(MethodSubject[]::new)));

    profileInspector.assertContainsNoOtherRules();
  }

  private static ClassSubject[] getCloseDispatcherSyntheticClasses(
      CodeInspector inspector, SyntheticItemsTestUtils syntheticItems) {
    return new ClassSubject[] {
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableDispatcherClass(
              Reference.classFromTypeName(FOO), 0)),
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableDispatcherClass(
              Reference.classFromTypeName(FOO), 1)),
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableDispatcherClass(
              Reference.classFromTypeName(BAR), 0)),
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableDispatcherClass(
              Reference.classFromTypeName(BAR), 1)),
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableForwarderClass(Reference.classFromTypeName(FOO), 2)),
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableForwarderClass(Reference.classFromTypeName(FOO), 3)),
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableForwarderClass(Reference.classFromTypeName(BAR), 2)),
      inspector.syntheticClass(
          syntheticItems.syntheticAutoCloseableForwarderClass(Reference.classFromTypeName(BAR), 3)),
      inspector.syntheticClass(
          syntheticItems.syntheticThrowIAEClass(Reference.classFromTypeName(FOO), 4)),
      inspector.syntheticClass(
          syntheticItems.syntheticThrowIAEClass(Reference.classFromTypeName(FOO), 5)),
      inspector.syntheticClass(
          syntheticItems.syntheticThrowIAEClass(Reference.classFromTypeName(BAR), 4)),
      inspector.syntheticClass(
          syntheticItems.syntheticThrowIAEClass(Reference.classFromTypeName(BAR), 5))
    };
  }
}
