// Copyright (c) 2020, 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.classmerging.horizontal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.R8FullTestBuilder;
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.classmerging.horizontal.NestClassMergingTestRunner.R.horizontalclassmerging.NestClassMergingTest;
import com.android.tools.r8.classmerging.horizontal.NestClassMergingTestRunner.R.horizontalclassmerging.NestHostA;
import com.android.tools.r8.classmerging.horizontal.NestClassMergingTestRunner.R.horizontalclassmerging.NestHostB;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesClass;
import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesJava11RootPackage;
import com.android.tools.r8.utils.ReflectiveBuildPathUtils.ExamplesPackage;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runners.Parameterized;

public class NestClassMergingTestRunner extends HorizontalClassMergingTestBase {

  public static class R extends ExamplesJava11RootPackage {
    public static class horizontalclassmerging extends ExamplesPackage {
      public static class NestClassMergingTest extends ExamplesClass {}

      public static class NestHostA extends ExamplesClass {
        public static class NestMemberA extends ExamplesClass {}

        public static class NestMemberB extends ExamplesClass {}
      }

      public static class NestHostB extends ExamplesClass {
        public static class NestMemberA extends ExamplesClass {}

        public static class NestMemberB extends ExamplesClass {}
      }
    }
  }

  public NestClassMergingTestRunner(TestParameters parameters) {
    super(parameters);
  }

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

  @Test
  public void test() throws Exception {
    runTest(
        builder ->
            builder.addHorizontallyMergedClassesInspector(
                inspector -> {
                  if (parameters.canUseNestBasedAccesses()) {
                    inspector
                        .assertIsCompleteMergeGroup(
                            classRef(NestHostA.class),
                            classRef(NestHostA.NestMemberA.class),
                            classRef(NestHostA.NestMemberB.class))
                        .assertIsCompleteMergeGroup(
                            classRef(NestHostB.class),
                            classRef(NestHostB.NestMemberA.class),
                            classRef(NestHostB.NestMemberB.class));
                  } else {
                    inspector.assertIsCompleteMergeGroup(
                        classRef(NestHostA.class),
                        classRef(NestHostA.NestMemberA.class),
                        classRef(NestHostA.NestMemberB.class),
                        classRef(NestHostB.class),
                        classRef(NestHostB.NestMemberA.class),
                        classRef(NestHostB.NestMemberB.class));
                  }
                }));
  }

  @Test
  public void testMergeHostIntoNestMemberA() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    runTest(
        builder ->
            builder
                .addHorizontallyMergedClassesInspector(
                    inspector ->
                        inspector
                            .assertIsCompleteMergeGroup(
                                classRef(NestHostA.class), classRef(NestHostA.NestMemberA.class))
                            .assertIsCompleteMergeGroup(
                                classRef(NestHostB.class), classRef(NestHostB.NestMemberA.class))
                            .assertClassReferencesNotMerged(
                                classRef(NestHostA.NestMemberB.class),
                                classRef(NestHostB.NestMemberB.class)))
                .addNoHorizontalClassMergingRule(
                    examplesTypeName(NestHostA.NestMemberB.class),
                    examplesTypeName(NestHostB.NestMemberB.class))
                .addOptionsModification(
                    options -> {
                      options.testing.horizontalClassMergingTarget =
                          (canditates, target) -> {
                            Set<ClassReference> candidateClassReferences =
                                Streams.stream(canditates)
                                    .map(DexClass::getClassReference)
                                    .collect(Collectors.toSet());
                            if (candidateClassReferences.contains(classRef(NestHostA.class))) {
                              assertEquals(
                                  ImmutableSet.of(
                                      classRef(NestHostA.class),
                                      classRef(NestHostA.NestMemberA.class)),
                                  candidateClassReferences);
                            } else {
                              assertEquals(
                                  ImmutableSet.of(
                                      classRef(NestHostB.class),
                                      classRef(NestHostB.NestMemberA.class)),
                                  candidateClassReferences);
                            }
                            return Iterables.find(
                                canditates,
                                candidate -> {
                                  ClassReference classReference = candidate.getClassReference();
                                  return classReference.equals(
                                          classRef(NestHostA.NestMemberA.class))
                                      || classReference.equals(
                                          classRef(NestHostB.NestMemberA.class));
                                });
                          };
                    }));
  }

  @Test
  public void testMergeHostIntoNestMemberB() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    runTest(
        builder ->
            builder
                .addHorizontallyMergedClassesInspector(
                    inspector ->
                        inspector
                            .assertIsCompleteMergeGroup(
                                classRef(NestHostA.class), classRef(NestHostA.NestMemberB.class))
                            .assertIsCompleteMergeGroup(
                                classRef(NestHostB.class), classRef(NestHostB.NestMemberB.class))
                            .assertClassReferencesNotMerged(
                                classRef(NestHostA.NestMemberA.class),
                                classRef(NestHostB.NestMemberA.class)))
                .addNoHorizontalClassMergingRule(
                    examplesTypeName(NestHostA.NestMemberA.class),
                    examplesTypeName(NestHostB.NestMemberA.class))
                .addOptionsModification(
                    options -> {
                      options.testing.horizontalClassMergingTarget =
                          (canditates, target) -> {
                            Set<ClassReference> candidateClassReferences =
                                Streams.stream(canditates)
                                    .map(DexClass::getClassReference)
                                    .collect(Collectors.toSet());
                            if (candidateClassReferences.contains(classRef(NestHostA.class))) {
                              assertEquals(
                                  ImmutableSet.of(
                                      classRef(NestHostA.class),
                                      classRef(NestHostA.NestMemberB.class)),
                                  candidateClassReferences);
                            } else {
                              assertEquals(
                                  ImmutableSet.of(
                                      classRef(NestHostB.class),
                                      classRef(NestHostB.NestMemberB.class)),
                                  candidateClassReferences);
                            }
                            return Iterables.find(
                                canditates,
                                candidate -> {
                                  ClassReference classReference = candidate.getClassReference();
                                  return classReference.equals(
                                          classRef(NestHostA.NestMemberB.class))
                                      || classReference.equals(
                                          classRef(NestHostB.NestMemberB.class));
                                });
                          };
                    }));
  }

  @Test
  public void testMergeMemberAIntoNestHost() throws Exception {
    assumeTrue(parameters.isCfRuntime());
    runTest(
        builder ->
            builder
                .addHorizontallyMergedClassesInspector(
                    inspector ->
                        inspector
                            .assertIsCompleteMergeGroup(
                                classRef(NestHostA.class), classRef(NestHostA.NestMemberA.class))
                            .assertIsCompleteMergeGroup(
                                classRef(NestHostB.class), classRef(NestHostB.NestMemberA.class))
                            .assertClassReferencesNotMerged(
                                classRef(NestHostA.NestMemberB.class),
                                classRef(NestHostB.NestMemberB.class)))
                .addNoHorizontalClassMergingRule(
                    examplesTypeName(NestHostA.NestMemberB.class),
                    examplesTypeName(NestHostB.NestMemberB.class))
                .addOptionsModification(
                    options -> {
                      options.testing.horizontalClassMergingTarget =
                          (canditates, target) -> {
                            Set<ClassReference> candidateClassReferences =
                                Streams.stream(canditates)
                                    .map(DexClass::getClassReference)
                                    .collect(Collectors.toSet());
                            if (candidateClassReferences.contains(classRef(NestHostA.class))) {
                              assertEquals(
                                  ImmutableSet.of(
                                      classRef(NestHostA.class),
                                      classRef(NestHostA.NestMemberA.class)),
                                  candidateClassReferences);
                            } else {
                              assertEquals(
                                  ImmutableSet.of(
                                      classRef(NestHostB.class),
                                      classRef(NestHostB.NestMemberA.class)),
                                  candidateClassReferences);
                            }
                            return Iterables.find(
                                canditates,
                                candidate -> {
                                  ClassReference classReference = candidate.getClassReference();
                                  return classReference.equals(classRef(NestHostA.class))
                                      || classReference.equals(classRef(NestHostB.class));
                                });
                          };
                    }));
  }

  private void runTest(ThrowableConsumer<R8FullTestBuilder> configuration) throws Exception {
    testForR8(parameters.getBackend())
        .addKeepMainRule(examplesTypeName(NestClassMergingTest.class))
        .addExamplesProgramFiles(R.class)
        .apply(configuration)
        .enableInliningAnnotations()
        .enableNeverClassInliningAnnotations()
        .setMinApi(parameters.getApiLevel())
        .compile()
        .run(parameters.getRuntime(), examplesTypeName(NestClassMergingTest.class))
        .assertSuccessWithOutputLines(
            "NestHostA$NestMemberA",
            "NestHostA$NestMemberB",
            "NestHostB$NestMemberA",
            "NestHostB$NestMemberB");
  }

  private static ClassReference classRef(Class<? extends ExamplesClass> clazz) {
    return examplesClassReference(clazz);
  }
}
