// 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.rewrite;

import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assume.assumeTrue;

import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.utils.StringUtils;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class JavaScriptScriptEngineTest extends ScriptEngineTestBase {

  private final TestParameters parameters;

  @Parameterized.Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withAllRuntimesAndApiLevels().build();
  }

  public JavaScriptScriptEngineTest(TestParameters parameters) {
    this.parameters = parameters;
  }

  private static String EXPECTED_RHINO_OUTPUT = StringUtils.lines("Mozilla Rhino", "42");
  private static String EXPECTED_NASHORN_OUTPUT = StringUtils.lines("Oracle Nashorn", "42");

  @Test
  public void testD8() throws IOException, CompilationFailedException, ExecutionException {
    assumeTrue("Only run D8 for dex backend", parameters.isDexRuntime());
    testForD8()
        .addInnerClasses(JavaScriptScriptEngineTest.class)
        .setMinApi(parameters.getApiLevel())
        .apply(this::addRhinoForAndroid)
        .compile()
        .run(parameters.getRuntime(), TestClassWithExplicitRhinoScriptEngineRegistration.class)
        .assertSuccessWithOutput(EXPECTED_RHINO_OUTPUT);
  }

  @Test
  public void testR8() throws IOException, CompilationFailedException, ExecutionException {
    testForR8(parameters.getBackend())
        .addInnerClasses(JavaScriptScriptEngineTest.class)
        .addKeepMainRule(TestClass.class)
        .setMinApi(parameters.getApiLevel())
        .applyIf(
            parameters.isDexRuntime(),
            testBuilder -> {
              testBuilder.addOptionsModification(
                  options ->
                      options
                          .getOpenClosedInterfacesOptions()
                          .suppressAllOpenInterfacesDueToMissingClasses());
              addRhinoForAndroid(testBuilder);
              addKeepRulesForAndroidRhino(testBuilder);
              testBuilder.allowDiagnosticWarningMessages();
            })
        .compile()
        .applyIf(
            parameters.isDexRuntime(),
            result ->
                result.assertAllWarningMessagesMatch(
                    anyOf(
                        containsString("Missing class "),
                        containsString(
                            "required for default or static interface methods desugaring"),
                        equalTo("Resource 'META-INF/MANIFEST.MF' already exists."))))
        .run(parameters.getRuntime(), TestClass.class)
        .applyIf(
            // TODO(b/227162584): Fails to find any engine on JDK17.
            parameters.isCfRuntime(CfVm.JDK17),
            r -> r.assertFailureWithErrorThatThrows(NullPointerException.class),
            r ->
                r.assertSuccessWithOutput(
                    parameters.isCfRuntime() ? EXPECTED_NASHORN_OUTPUT : EXPECTED_RHINO_OUTPUT));
  }

  static class TestClass {
    public final ScriptEngineManager manager = new ScriptEngineManager();

    public void run() throws Exception {
      ScriptEngine engine = manager.getEngineByMimeType("text/javascript");
      System.out.println(engine.getFactory().getEngineName());
      runJavaScript(engine);
    }

    public void runJavaScript(ScriptEngine engine) throws Exception {
      // Add a simple JavaScript function and call it.
      engine.eval("function add(x, y) { return x + y }");
      Object fortyTwo = engine.eval("add(40, 2)");
      // Rhino and Nashorn in JDK8 returns a Double. Nashorn in JDK9 and JDK11 returns an Integer.
      if (fortyTwo instanceof Double) {
        System.out.println(((Double) fortyTwo).intValue());
      } else if (fortyTwo instanceof Integer) {
        System.out.println(fortyTwo);
      } else {
        System.out.println("Unexpected");
      }
    }

    public static void main(String[] args) throws Exception {
      new TestClass().run();
    }
  }

  static class TestClassWithExplicitRhinoScriptEngineRegistration extends TestClass {

    public TestClassWithExplicitRhinoScriptEngineRegistration() throws Exception {
      // D8 does not handle META-INF/services, it just produces dex files, so register
      // the Rhino engine directly.
      manager.registerEngineMimeType(
          "text/javascript",
          (ScriptEngineFactory)
              (Class.forName("com.sun.script.javascript.RhinoScriptEngineFactory")
                  .getConstructor()
                  .newInstance()));
    }

    public static void main(String[] args) throws Exception {
      new TestClassWithExplicitRhinoScriptEngineRegistration().run();
    }
  }
}
