// 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 com.android.tools.r8.naming;

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

import com.android.tools.r8.NeverInline;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class NonMemberClassTest extends TestBase {

  static class Enclosing {
    @NeverInline
    void foo() {
      class Local {
        Local() {
          if (this.getClass().getEnclosingClass() != null) {
            System.out.println("I'm local.");
          }
        }
      }
      new Local();

      Runnable r = new Runnable() {
        @NeverInline
        @Override
        public void run() {
          if (this.getClass().isAnonymousClass()) {
            System.out.println("I'm anonymous.");
          }
        }
      };
      r.run();
    }
  }

  static class TestMain {
    public static void main(String... args) {
      new Enclosing().foo();
    }
  }

  enum TestConfig {
    KEEP_INNER_CLASSES,
    KEEP_ALLOW_MINIFICATION,
    NO_KEEP_NO_MINIFICATION,
    NO_KEEP_MINIFICATION;

    public String getKeepRules() {
      switch (this) {
        case KEEP_INNER_CLASSES:
          return "-keep class " + Enclosing.class.getName() + "$*";
        case KEEP_ALLOW_MINIFICATION:
          return "-keep,allowobfuscation class " + Enclosing.class.getName() + "$*";
        case NO_KEEP_NO_MINIFICATION:
          return "-dontobfuscate";
        case NO_KEEP_MINIFICATION:
          return "";
        default:
          throw new Unreachable();
      }
    }

    public String getExpectedOutput(TestParameters parameters, boolean isFullMode) {
      switch (this) {
        case KEEP_INNER_CLASSES:
          return JVM_OUTPUT;
        case KEEP_ALLOW_MINIFICATION:
          if (parameters.isCfRuntime()
              && parameters.getRuntime().asCf().getVm().lessThanOrEqual(CfVm.JDK8)) {
            return MINIFIED_OUTPUT_JDK8;
          }
          return JVM_OUTPUT;
        case NO_KEEP_NO_MINIFICATION:
          // In full mode, we remove all attributes since nothing pinned, i.e., no reflection uses.
          return isFullMode ? "" : JVM_OUTPUT;
        case NO_KEEP_MINIFICATION:
          // In full mode, we remove all attributes since nothing pinned, i.e., no reflection uses.
          if (isFullMode) {
            return "";
          }
          if (parameters.isCfRuntime()
              && parameters.getRuntime().asCf().getVm().lessThanOrEqual(CfVm.JDK8)) {
            return MINIFIED_OUTPUT_JDK8;
          }
          return JVM_OUTPUT;
        default:
          throw new Unreachable();
      }
    }

    public void inspect(boolean isFullMode, CodeInspector inspector) {
      int expectedNumberOfNonMemberInnerClasses;
      switch (this) {
        case KEEP_INNER_CLASSES:
        case KEEP_ALLOW_MINIFICATION:
          expectedNumberOfNonMemberInnerClasses = 2;
          break;
        case NO_KEEP_NO_MINIFICATION:
        case NO_KEEP_MINIFICATION:
          expectedNumberOfNonMemberInnerClasses = isFullMode ? 0 : 2;
          break;
        default:
          throw new Unreachable();
      }
      assertEquals(
          expectedNumberOfNonMemberInnerClasses,
          inspector.allClasses().stream()
              .filter(
                  classSubject ->
                      classSubject.getDexProgramClass().isLocalClass()
                          || classSubject.getDexProgramClass().isAnonymousClass())
              .count());
    }
  }

  private static final Class<?> MAIN = TestMain.class;

  // Since JDK9, a class is determined as anonymous if the inner-name in the associated inner-class
  // attribute is empty.
  // JDK8 determines an anonymous class differently: checking if a simple name is empty.
  // Moreover, it computes the simple name differently: some assumptions about non-member classes,
  // e.g., 1 or more digits (followed by the simple name if it's local).
  // Since JDK9, the simple name is computed by stripping off the package name.
  // See b/132808897 for more details.
  private static final String MINIFIED_OUTPUT_JDK8 = StringUtils.lines(
      "I'm local."
  );
  private static final String JVM_OUTPUT = StringUtils.lines(
      "I'm local.",
      "I'm anonymous."
  );

  private final TestParameters parameters;
  private final TestConfig config;

  @Parameterized.Parameters(name = "{0} {1}")
  public static Collection<Object[]> data() {
    return buildParameters(
        getTestParameters().withAllRuntimes().withAllApiLevels().build(), TestConfig.values());
  }

  public NonMemberClassTest(TestParameters parameters, TestConfig config) {
    this.parameters = parameters;
    this.config = config;
  }

  @Test
  public void testJVMOutput() throws Exception {
    assumeTrue(
        "Only run JVM reference on CF runtimes",
        parameters.isCfRuntime() && config == TestConfig.NO_KEEP_NO_MINIFICATION);
    testForJvm()
        .addTestClasspath()
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(JVM_OUTPUT);
  }

  @Test
  public void testR8Compat() throws Exception {
    testForR8Compat(parameters.getBackend())
        .addInnerClasses(NonMemberClassTest.class)
        .addKeepMainRule(MAIN)
        .addKeepRules(config.getKeepRules())
        .addKeepAttributes("Signature", "InnerClasses", "EnclosingMethod")
        .enableInliningAnnotations()
        .setMinApi(parameters.getApiLevel())
        .addOptionsModification(options -> options.enableClassInlining = false)
        .compile()
        .inspect(inspector -> config.inspect(false, inspector))
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(config.getExpectedOutput(parameters, false));
  }

  @Test
  public void testR8() throws Exception {
    testForR8(parameters.getBackend())
        .addInnerClasses(NonMemberClassTest.class)
        .addKeepMainRule(MAIN)
        .addKeepRules(config.getKeepRules())
        .addKeepAttributes("Signature", "InnerClasses", "EnclosingMethod")
        .enableInliningAnnotations()
        .setMinApi(parameters.getApiLevel())
        .addOptionsModification(options -> options.enableClassInlining = false)
        .compile()
        .inspect(inspector -> config.inspect(true, inspector))
        .run(parameters.getRuntime(), MAIN)
        .assertSuccessWithOutput(config.getExpectedOutput(parameters, true));
  }
}
