// Copyright (c) 2019, 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 nesthostexample;

import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertSame;
import static junit.framework.TestCase.assertTrue;

import com.android.tools.r8.Jdk9TestUtils;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.ThrowableConsumer;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.NestMemberClassAttribute;
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.FoundClassSubject;
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 NestAttributesUpdateTest extends TestBase {
  private static final String PACKAGE_NAME = "nesthostexample.";

  private static final Class<?> MERGING_OUTER_CLASS = BasicNestHostClassMerging.class;
  private static final Class<?> PRUNING_OUTER_CLASS = BasicNestHostTreePruning.class;
  private static final String MERGING_EXPECTED_RESULT = StringUtils.lines("OuterMiddleInner");
  private static final String PRUNING_EXPECTED_RESULT = StringUtils.lines("NotPruned");

  @Parameter(0)
  public TestParameters parameters;

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

  @Test
  public void testClassMergingNestMemberRemoval() throws Exception {
    testNestAttributesCorrect(
        MERGING_OUTER_CLASS,
        MERGING_OUTER_CLASS,
        MERGING_EXPECTED_RESULT,
        3,
        ThrowableConsumer.empty());
  }

  @Test
  public void testClassMergingNestHostRemoval() throws Exception {
    testNestAttributesCorrect(
        BasicNestHostClassMerging.MiddleOuter.class,
        MERGING_OUTER_CLASS,
        MERGING_EXPECTED_RESULT,
        2,
        builder ->
            builder.addOptionsModification(
                internalOptions -> {
                  // The test makes an invoke to StringConcatFactory which is not known to DEX and
                  // we therefore fail to merge the classes.
                  internalOptions.apiModelingOptions().enableApiCallerIdentification = false;
                }));
  }

  @Test
  public void testTreePruningNestMemberRemoval() throws Exception {
    testNestAttributesCorrect(
        PRUNING_OUTER_CLASS,
        PRUNING_OUTER_CLASS,
        PRUNING_EXPECTED_RESULT,
        2,
        ThrowableConsumer.empty());
  }

  @Test
  public void testTreePruningNestHostRemoval() throws Exception {
    testNestAttributesCorrect(
        BasicNestHostTreePruning.Pruned.class,
        PRUNING_OUTER_CLASS,
        PRUNING_EXPECTED_RESULT,
        1,
        ThrowableConsumer.empty());
  }

  public void testNestAttributesCorrect(
      Class<?> mainClass,
      Class<?> outerNestClass,
      String expectedResult,
      int expectedNumClassesLeft,
      ThrowableConsumer<R8FullTestBuilder> testBuilderConsumer)
      throws Exception {
    testNestAttributesCorrect(
        mainClass,
        outerNestClass,
        expectedResult,
        true,
        expectedNumClassesLeft,
        testBuilderConsumer);
    testNestAttributesCorrect(
        mainClass,
        outerNestClass,
        expectedResult,
        false,
        expectedNumClassesLeft,
        testBuilderConsumer);
  }

  public void testNestAttributesCorrect(
      Class<?> mainClass,
      Class<?> outerNestClass,
      String expectedResult,
      boolean minification,
      int expectedNumClassesLeft,
      ThrowableConsumer<R8FullTestBuilder> testBuilderConsumer)
      throws Exception {
    testForR8(parameters.getBackend())
        .addKeepMainRule(mainClass)
        .minification(minification)
        .addOptionsModification(
            options -> {
              // Disable optimizations else additional classes are removed since they become unused.
              options.enableClassInlining = false;
            })
        .addProgramClassesAndInnerClasses(outerNestClass)
        .applyIf(parameters.isCfRuntime(), Jdk9TestUtils.addJdk9LibraryFiles(temp))
        .addKeepPackageNamesRule("nesthostexample")
        .addInliningAnnotations()
        .apply(testBuilderConsumer)
        .compile()
        .inspect(
            inspector -> {
              assertEquals(expectedNumClassesLeft, inspector.allClasses().size());
              assertNestAttributesCorrect(inspector);
            })
        .run(parameters.getRuntime(), mainClass)
        .assertSuccessWithOutput(expectedResult);
  }

  public static void assertNestAttributesCorrect(CodeInspector inspector) {
    assertFalse(inspector.allClasses().isEmpty());
    for (FoundClassSubject classSubject : inspector.allClasses()) {
      DexClass clazz = classSubject.getDexProgramClass();
      if (clazz.isInANest()) {
        if (clazz.isNestHost()) {
          // All members are present with the clazz as host
          for (NestMemberClassAttribute attr : clazz.getNestMembersClassAttributes()) {
            String memberName = attr.getNestMember().getName();
            ClassSubject inner = inspector.clazz(PACKAGE_NAME + memberName);
            assertNotNull(
                "The nest member " + memberName + " of " + clazz.type.getName() + " is missing",
                inner.getDexProgramClass());
            assertSame(inner.getDexProgramClass().getNestHost(), clazz.type);
          }
        } else {
          // Nest host is present and with the clazz as member
          String hostName = clazz.getNestHost().getName();
          ClassSubject host = inspector.clazz(PACKAGE_NAME + hostName);
          assertNotNull(
              "The nest host " + hostName + " of " + clazz.type.getName() + " is missing",
              host.getDexProgramClass());
          assertTrue(
              host.getDexProgramClass().getNestMembersClassAttributes().stream()
                  .anyMatch(attr -> attr.getNestMember() == clazz.type));
        }
      }
    }
  }
}
