// 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 com.android.tools.r8.TestRuntime.CfVm;
import com.android.tools.r8.TestRuntime.NoneRuntime;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.utils.AndroidApiLevel;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestParametersBuilder {

  // Static computation of VMs configured as available by the testing invocation.
  private static final List<TestRuntime> availableRuntimes =
      getAvailableRuntimes().collect(Collectors.toList());

  // Predicate describing which test parameters are applicable to the test.
  // Built via the methods found below. Defaults to no applicable parameters, i.e., the emtpy set.
  private Predicate<TestParameters> filter = param -> false;
  private boolean hasDexRuntimeFilter = false;

  private TestParametersBuilder() {}

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

  private TestParametersBuilder withFilter(Predicate<TestParameters> predicate) {
    filter = filter.or(predicate);
    return this;
  }

  private TestParametersBuilder withCfRuntimeFilter(Predicate<CfVm> predicate) {
    return withFilter(p -> p.isCfRuntime() && predicate.test(p.getRuntime().asCf().getVm()));
  }

  private TestParametersBuilder withDexRuntimeFilter(Predicate<DexVm.Version> predicate) {
    hasDexRuntimeFilter = true;
    return withFilter(
        p -> p.isDexRuntime() && predicate.test(p.getRuntime().asDex().getVm().getVersion()));
  }

  public TestParametersBuilder withNoneRuntime() {
    return withFilter(p -> p.getRuntime() == NoneRuntime.getInstance());
  }

  public TestParametersBuilder withAllRuntimes() {
    return withCfRuntimes().withDexRuntimes();
  }

  public TestParametersBuilder withAllRuntimesAndApiLevels() {
    return withCfRuntimes().withDexRuntimes().withAllApiLevels();
  }

  /** Add specific runtime if available. */
  public TestParametersBuilder withCfRuntime(CfVm runtime) {
    return withCfRuntimeFilter(vm -> vm == runtime);
  }

  /** Add all available CF runtimes. */
  public TestParametersBuilder withCfRuntimes() {
    return withCfRuntimeFilter(vm -> true);
  }

  /** Add all available CF runtimes between {@param startInclusive} and {@param endInclusive}. */
  public TestParametersBuilder withCfRuntimes(CfVm startInclusive, CfVm endInclusive) {
    return withCfRuntimeFilter(
        vm -> startInclusive.lessThanOrEqual(vm) && vm.lessThanOrEqual(endInclusive));
  }

  /** Add all available CF runtimes starting from and including {@param startInclusive}. */
  public TestParametersBuilder withCfRuntimesStartingFromIncluding(CfVm startInclusive) {
    return withCfRuntimeFilter(vm -> startInclusive.lessThanOrEqual(vm));
  }

  /** Add all available CF runtimes starting from and excluding {@param startExcluding}. */
  public TestParametersBuilder withCfRuntimesStartingFromExcluding(CfVm startExcluding) {
    return withCfRuntimeFilter(vm -> startExcluding.lessThan(vm));
  }

  /** Add all available CF runtimes ending at and including {@param endInclusive}. */
  public TestParametersBuilder withCfRuntimesEndingAtIncluding(CfVm endInclusive) {
    return withCfRuntimeFilter(vm -> vm.lessThanOrEqual(endInclusive));
  }

  /** Add all available CF runtimes ending at and excluding {@param endExclusive}. */
  public TestParametersBuilder withCfRuntimesEndingAtExcluding(CfVm endExclusive) {
    return withCfRuntimeFilter(vm -> vm.lessThan(endExclusive));
  }

  /** Add all available DEX runtimes. */
  public TestParametersBuilder withDexRuntimes() {
    return withDexRuntimeFilter(vm -> true);
  }

  /** Add specific runtime if available. */
  public TestParametersBuilder withDexRuntime(DexVm.Version runtime) {
    return withDexRuntimeFilter(vm -> vm == runtime);
  }

  /** Add all available CF runtimes between {@param startInclusive} and {@param endInclusive}. */
  public TestParametersBuilder withDexRuntimes(
      DexVm.Version startInclusive, DexVm.Version endInclusive) {
    return withDexRuntimeFilter(
        vm -> startInclusive.isOlderThanOrEqual(vm) && vm.isOlderThanOrEqual(endInclusive));
  }

  /** Add all available DEX runtimes that support native multidex. */
  public TestParametersBuilder withNativeMultidexDexRuntimes() {
    return withDexRuntimesStartingFromIncluding(DexVm.Version.V5_1_1);
  }

  /** Add all available DEX runtimes starting from and including {@param startInclusive}. */
  public TestParametersBuilder withDexRuntimesStartingFromIncluding(DexVm.Version startInclusive) {
    return withDexRuntimeFilter(vm -> startInclusive.isOlderThanOrEqual(vm));
  }

  /** Add all available DEX runtimes starting from and excluding {@param startExcluding}. */
  public TestParametersBuilder withDexRuntimesStartingFromExcluding(DexVm.Version startExcluding) {
    return withDexRuntimeFilter(
        vm -> vm != startExcluding && startExcluding.isOlderThanOrEqual(vm));
  }

  /** Add all available DEX runtimes ending at and including {@param endInclusive}. */
  public TestParametersBuilder withDexRuntimesEndingAtIncluding(DexVm.Version endInclusive) {
    return withDexRuntimeFilter(vm -> vm.isOlderThanOrEqual(endInclusive));
  }

  /** Add all available DEX runtimes ending at and excluding {@param endExclusive}. */
  public TestParametersBuilder withDexRuntimesEndingAtExcluding(DexVm.Version endExclusive) {
    return withDexRuntimeFilter(vm -> vm != endExclusive && vm.isOlderThanOrEqual(endExclusive));
  }

  /**
   * API level configuration.
   *
   * <p>Currently enabling API level config will by default configure each DEX VM to be configured
   * with two parameters, one running at the highest api-level supported by the VM and one at the
   * lowest supported by the compiler (i.e., B).
   */
  private static final AndroidApiLevel lowestCompilerApiLevel = AndroidApiLevel.B;

  private boolean enableApiLevels = false;

  private Predicate<AndroidApiLevel> apiLevelFilter = param -> false;

  private TestParametersBuilder withApiFilter(Predicate<AndroidApiLevel> filter) {
    enableApiLevels = true;
    apiLevelFilter = apiLevelFilter.or(filter);
    return this;
  }

  public TestParametersBuilder withAllApiLevels() {
    return withApiFilter(api -> true);
  }

  public TestParametersBuilder withApiLevelsStartingAtIncluding(AndroidApiLevel startInclusive) {
    return withApiFilter(api -> startInclusive.getLevel() <= api.getLevel());
  }

  public TestParametersBuilder withApiLevelsStartingAtExcluding(AndroidApiLevel startExclusive) {
    return withApiFilter(api -> startExclusive.getLevel() < api.getLevel());
  }

  public TestParametersBuilder withApiLevelsEndingAtIncluding(AndroidApiLevel endInclusive) {
    return withApiFilter(api -> api.getLevel() <= endInclusive.getLevel());
  }

  public TestParametersBuilder withApiLevelsEndingAtExcluding(AndroidApiLevel endExclusive) {
    return withApiFilter(api -> api.getLevel() < endExclusive.getLevel());
  }

  public TestParametersCollection build() {
    assert !enableApiLevels || hasDexRuntimeFilter;
    return new TestParametersCollection(
        getAvailableRuntimes()
            .flatMap(this::createParameters)
            .filter(filter)
            .collect(Collectors.toList()));
  }

  public Stream<TestParameters> createParameters(TestRuntime runtime) {
    if (!enableApiLevels || !runtime.isDex()) {
      return Stream.of(new TestParameters(runtime));
    }
    List<AndroidApiLevel> sortedApiLevels =
        AndroidApiLevel.getAndroidApiLevelsSorted().stream()
            .filter(apiLevelFilter)
            .collect(Collectors.toList());
    if (sortedApiLevels.isEmpty()) {
      return Stream.of();
    }
    AndroidApiLevel vmLevel = runtime.asDex().getMinApiLevel();
    AndroidApiLevel lowestApplicable = sortedApiLevels.get(0);
    if (vmLevel.getLevel() < lowestApplicable.getLevel()) {
      return Stream.of();
    }
    if (sortedApiLevels.size() > 1) {
      for (int i = sortedApiLevels.size() - 1; i >= 0; i--) {
        AndroidApiLevel highestApplicable = sortedApiLevels.get(i);
        if (highestApplicable.getLevel() <= vmLevel.getLevel()
            && lowestApplicable != highestApplicable) {
          return Stream.of(
              new TestParameters(runtime, lowestApplicable),
              new TestParameters(runtime, highestApplicable));
        }
      }
    }
    return Stream.of(new TestParameters(runtime, lowestApplicable));
  }

  // Public method to check that the CF runtime coincides with the system runtime.
  public static boolean isSystemJdk(CfVm vm) {
    TestRuntime systemRuntime = TestRuntime.getSystemRuntime();
    return systemRuntime.isCf() && systemRuntime.asCf().getVm().equals(vm);
  }

  public static boolean isRuntimesPropertySet() {
    return getRuntimesProperty() != null;
  }

  public static String getRuntimesProperty() {
    return System.getProperty("runtimes");
  }

  private static Stream<TestRuntime> getUnfilteredAvailableRuntimes() {
    // The runtimes are built in a linked hash map to ensure a deterministic order and avoid
    // duplicates.
    LinkedHashMap<TestRuntime, TestRuntime> runtimes = new LinkedHashMap<>();
    // Place the none-runtime first.
    NoneRuntime noneRuntime = NoneRuntime.getInstance();
    runtimes.putIfAbsent(noneRuntime, noneRuntime);
    // Then the checked in runtimes (CF and DEX).
    for (TestRuntime checkedInRuntime : TestRuntime.getCheckedInRuntimes()) {
      runtimes.putIfAbsent(checkedInRuntime, checkedInRuntime);
    }
    // Then finally the system runtime. It will likely be the same as a checked in and adding it
    // makes the overall order more stable.
    TestRuntime systemRuntime = TestRuntime.getSystemRuntime();
    runtimes.putIfAbsent(systemRuntime, systemRuntime);
    return runtimes.values().stream();
  }

  private static Stream<TestRuntime> getAvailableRuntimes() {
    if (isRuntimesPropertySet()) {
      String[] runtimeFilters = getRuntimesProperty().split(":");
      return getUnfilteredAvailableRuntimes()
          .filter(
              runtime ->
                  Arrays.stream(runtimeFilters).anyMatch(filter -> runtime.name().equals(filter)));
    }
    return getUnfilteredAvailableRuntimes();
  }

  public static List<CfVm> getAvailableCfVms() {
    return getAvailableRuntimes()
        .filter(TestRuntime::isCf)
        .map(runtime -> runtime.asCf().getVm())
        .collect(Collectors.toList());
  }

  public static List<DexVm> getAvailableDexVms() {
    return getAvailableRuntimes()
        .filter(TestRuntime::isDex)
        .map(runtime -> runtime.asDex().getVm())
        .collect(Collectors.toList());
  }
}
