// 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.getDexClass().isLocalClass()
                  || classSubject.getDexClass().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));
  }
}
