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

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

import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.TestRuntime.DexRuntime;
import com.android.tools.r8.TestRuntime.NoneRuntime;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.nio.file.Path;

// Actual test parameters for a specific configuration. Currently just the runtime configuration.
public class TestParameters {

  private final TestRuntime runtime;
  private final AndroidApiLevel apiLevel;
  private final boolean representativeApiLevelForRuntime;

  public TestParameters(TestRuntime runtime) {
    this(runtime, null);
  }

  public TestParameters(TestRuntime runtime, AndroidApiLevel apiLevel) {
    this(runtime, apiLevel, true);
  }

  public TestParameters(
      TestRuntime runtime, AndroidApiLevel apiLevel, boolean representativeApiLevelForRuntime) {
    assert runtime != null;
    this.runtime = runtime;
    this.apiLevel = apiLevel;
    this.representativeApiLevelForRuntime = representativeApiLevelForRuntime;
  }

  public static TestParametersBuilder builder() {
    return new TestParametersBuilder();
  }

  public static TestParametersCollection justNoneRuntime() {
    return builder().withNoneRuntime().build();
  }

  public boolean canHaveIssueWithInlinedMonitors() {
    return isCfRuntime() || getApiLevel().isLessThanOrEqualTo(AndroidApiLevel.M);
  }

  /**
   * Returns true if the runtime uses resolution to lookup the constructor targeted by a given
   * invoke, so that it is valid to have non-rebound constructor invokes.
   *
   * <p>Example: If value `v` is an uninitialized instanceof type `T`, then calling `T.<init>()`
   * succeeds on ART even if `T.<init>()` does not exists, as ART will resolve the constructor, find
   * `Object.<init>()`, and use this method to initialize `v`. On the JVM and on Dalvik, this is a
   * runtime error.
   */
  public boolean canHaveNonReboundConstructorInvoke() {
    return isDexRuntime() && getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.L);
  }

  public boolean canInitNewInstanceUsingSuperclassConstructor() {
    return canHaveNonReboundConstructorInvoke();
  }

  public boolean canUseDefaultAndStaticInterfaceMethods() {
    assert isCfRuntime() || isDexRuntime();
    assert !isCfRuntime() || apiLevel == null
        : "Use canUseDefaultAndStaticInterfaceMethodsWhenDesugaring when using CF api levels.";
    return isCfRuntime()
        || getApiLevel()
            .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport());
  }

  public boolean canUseDefaultAndStaticInterfaceMethodsWhenDesugaring() {
    assert isCfRuntime() || isDexRuntime();
    assert apiLevel != null;
    return getApiLevel()
        .isGreaterThanOrEqualTo(TestBase.apiLevelWithDefaultInterfaceMethodsSupport());
  }

  public boolean canUseNativeDexPC() {
    assert isCfRuntime() || isDexRuntime();
    return isDexRuntime() && getDexRuntimeVersion().isNewerThanOrEqual(DexVm.Version.V8_1_0);
  }

  public boolean canUseNativeMultidex() {
    return isDexRuntime() && getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.L);
  }

  public boolean canUseNestBasedAccesses() {
    assert isCfRuntime() || isDexRuntime();
    return isCfRuntime() && getRuntime().asCf().isNewerThanOrEqual(CfVm.JDK11);
  }

  public boolean canUseNestBasedAccessesWhenDesugaring() {
    assert isCfRuntime() || isDexRuntime();
    assert apiLevel != null;
    return false;
  }

  public boolean canUseFilledNewArrayOnNonStringObjects() {
    return isDexRuntime() && getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N);
  }

  public boolean canUseSubTypesInFilledNewArray() {
    return isDexRuntime() && getApiLevel().isGreaterThan(AndroidApiLevel.U);
  }

  public boolean isAccessModificationEnabled(boolean allowAccessModification) {
    return allowAccessModification || isAccessModificationEnabledByDefault();
  }

  public boolean isAccessModificationEnabledByDefault() {
    return true;
  }

  public boolean runtimeWithClassValue() {
    assert isCfRuntime() || isDexRuntime();
    return isCfRuntime() || getDexRuntimeVersion().isNewerThanOrEqual(DexVm.Version.V14_0_0);
  }

  // Convenience predicates.
  public boolean isDexRuntime() {
    return runtime.isDex();
  }

  public DexRuntime asDexRuntime() {
    return getRuntime().asDex();
  }

  public boolean isCfRuntime() {
    return runtime.isCf();
  }

  public boolean isCfRuntime(CfVm vm) {
    return runtime.isCf() && runtime.asCf().getVm() == vm;
  }

  public CfRuntime asCfRuntime() {
    return getRuntime().asCf();
  }

  public boolean isDexRuntimeVersion(DexVm.Version vm) {
    return isDexRuntime() && getDexRuntimeVersion().isEqualTo(vm);
  }

  public boolean isDexRuntimeVersionNewerThanOrEqual(DexVm.Version vm) {
    return isDexRuntime() && getDexRuntimeVersion().isNewerThanOrEqual(vm);
  }

  public boolean isDexRuntimeVersionOlderThanOrEqual(DexVm.Version vm) {
    return isDexRuntime() && getDexRuntimeVersion().isOlderThanOrEqual(vm);
  }

  public boolean isNoneRuntime() {
    return runtime == NoneRuntime.getInstance();
  }

  public void configureApiLevel(TestAppViewBuilder testAppViewBuilder) {
    testAppViewBuilder.setMinApi(apiLevel);
  }

  public void configureApiLevel(TestCompilerBuilder<?, ?, ?, ?, ?> testCompilerBuilder) {
    testCompilerBuilder.setMinApi(apiLevel);
  }

  // TODO(b/270021825): Tests should not access the underlying API level directly, but may be
  //  allowed to query if the api level satisfies some condition.
  @Deprecated
  public AndroidApiLevel getApiLevel() {
    if (runtime.isDex() && apiLevel == null) {
      throw new RuntimeException(
          "Use of getApiLevel without configured API levels for TestParametersCollection.");
    }
    return apiLevel;
  }

  public Path getDefaultAndroidJar() {
    assert isDexRuntime();
    return ToolHelper.getFirstSupportedAndroidJar(getApiLevel());
  }

  public Path getDefaultAndroidJarAbove(AndroidApiLevel minimumCompileApiLevel) {
    assert isDexRuntime();
    return ToolHelper.getFirstSupportedAndroidJar(getApiLevel().max(minimumCompileApiLevel));
  }

  public Path getDefaultRuntimeLibrary() {
    return isCfRuntime() ? ToolHelper.getJava8RuntimeJar() : getDefaultAndroidJar();
  }

  public CfRuntime getCfRuntime() {
    assert isCfRuntime();
    return runtime.asCf();
  }

  // Access to underlying runtime/wrapper.
  public TestRuntime getRuntime() {
    return runtime;
  }

  public boolean isOrSimulateNoneRuntime() {
    return isNoneRuntime()
        || (runtime != null && runtime.equals(TestRuntime.getDefaultCfRuntime()));
  }

  // Helper function to get the "backend" for a given runtime target.
  public Backend getBackend() {
    return runtime.getBackend();
  }

  @Override
  public String toString() {
    if (apiLevel != null) {
      return runtime.toString() + ", api:" + apiLevel.getLevel();
    }
    return runtime.toString();
  }

  public void assertCfRuntime() {
    assertTrue(runtime.isCf());
  }

  public void assertNoneRuntime() {
    assertEquals(NoneRuntime.getInstance(), runtime);
  }

  public void assertIsRepresentativeApiLevelForRuntime() {
    assertTrue(representativeApiLevelForRuntime);
  }

  public TestParameters assumeCfRuntime() {
    assumeTrue(isCfRuntime());
    return this;
  }

  public TestParameters assumeDexRuntime() {
    assumeTrue(isDexRuntime());
    return this;
  }

  public TestParameters assumeIsOrSimulateNoneRuntime() {
    assumeTrue(isOrSimulateNoneRuntime());
    return this;
  }

  public boolean isJvmTestParameters() {
    if (isCfRuntime()) {
      return apiLevel == null || representativeApiLevelForRuntime;
    }
    return false;
  }

  public TestParameters assumeJvmTestParameters() {
    assumeCfRuntime();
    assumeTrue(apiLevel == null || representativeApiLevelForRuntime);
    return this;
  }

  public TestParameters assumeProguardTestParameters() {
    assumeCfRuntime();
    assumeTrue(apiLevel == null || representativeApiLevelForRuntime);
    return this;
  }

  public TestParameters assumeR8TestParameters() {
    assumeTrue(isR8TestParameters());
    return this;
  }

  public boolean isR8TestParameters() {
    assertFalse(
        "No need to use is/assumeR8TestParameters() when not using api levels for CF",
        isCfRuntime() && apiLevel == null);
    assertTrue(apiLevel != null || representativeApiLevelForRuntime);
    return isDexRuntime() || representativeApiLevelForRuntime;
  }

  public TestParameters assumeRuntimeTestParameters() {
    assertFalse(
        "No need to use assumeRuntimeTestParameters() when not using api levels for CF",
        apiLevel == null);
    assumeTrue(isDexRuntime() || representativeApiLevelForRuntime);
    return this;
  }

  public DexVm.Version getDexRuntimeVersion() {
    assertTrue(isDexRuntime());
    return getRuntime().asDex().getVm().getVersion();
  }
}
