// 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.Assume.assumeTrue;

import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableMap;
import java.nio.file.Path;
import java.nio.file.Paths;

// Base class for the runtime structure in the test parameters.
public class TestRuntime {

  public static TestRuntime fromName(String name) {
    if (NoneRuntime.NAME.equals(name)) {
      return NoneRuntime.getInstance();
    }
    CfVm cfVm = CfVm.fromName(name);
    if (cfVm != null) {
      return new CfRuntime(cfVm);
    }
    if (name.startsWith("dex-")) {
      DexVm dexVm = DexVm.fromShortName(name.substring(4) + "_host");
      if (dexVm != null) {
        return new DexRuntime(dexVm);
      }
    }
    return null;
  }

  // Enum describing the possible/supported CF runtimes.
  public enum CfVm {
    JDK8("jdk8"),
    JDK9("jdk9"),
    JDK11("jdk11");

    private final String name;

    public static CfVm fromName(String v) {
      for (CfVm value : CfVm.values()) {
        if (value.name.equals(v)) {
          return value;
        }
      }
      return null;
    }

    CfVm(String name) {
      this.name = name;
    }

    public static CfVm first() {
      return JDK8;
    }

    public static CfVm last() {
      return JDK11;
    }

    public boolean lessThan(CfVm other) {
      return this.ordinal() < other.ordinal();
    }

    public boolean lessThanOrEqual(CfVm other) {
      return this.ordinal() <= other.ordinal();
    }

    @Override
    public String toString() {
      return name;
    }
  }

  // Values are the path in third_party/openjdk to the repository with bin
  public static ImmutableMap<CfVm, Path> CHECKED_IN_JDKS = initializeCheckedInJDKs();

  public static ImmutableMap<CfVm, Path> initializeCheckedInJDKs() {
    if (ToolHelper.isLinux()) {
      return ImmutableMap.of(
          CfVm.JDK8,
          Paths.get("jdk8", "linux-x86"),
          CfVm.JDK9,
          Paths.get("openjdk-9.0.4", "linux"),
          CfVm.JDK11,
          Paths.get("jdk-11", "Linux"));
    }
    if (ToolHelper.isMac()) {
      return ImmutableMap.of(
          CfVm.JDK8,
          Paths.get("jdk8", "darwin-x86"),
          CfVm.JDK9,
          Paths.get("openjdk-9.0.4", "osx"),
          CfVm.JDK11,
          Paths.get("jdk-11", "Mac"));
    }
    assert ToolHelper.isWindows();
    return ImmutableMap.of(
        CfVm.JDK9,
        Paths.get("openjdk-9.0.4", "windows"),
        CfVm.JDK11,
        Paths.get("jdk-11", "Windows"));
  }

  public static boolean isCheckedInJDK(CfVm jdk) {
    // Non-linux checked-in jdk support has never been tested,
    // so we pretend they do not exist.
    if (!ToolHelper.isLinux()) {
      return false;
    }
    return CHECKED_IN_JDKS.containsKey(jdk);
  }

  public static Path getCheckInJDKPathFor(CfVm jdk) {
    assumeTrue(ToolHelper.isLinux());
    return Paths.get("third_party", "openjdk")
        .resolve(CHECKED_IN_JDKS.get(jdk))
        .resolve(Paths.get("bin", "java"));
  }

  public static TestRuntime getDefaultJavaRuntime() {
    // For compatibility with old tests not specifying a Java runtime
    return new CfRuntime(CfVm.JDK9);
  }

  public static class NoneRuntime extends TestRuntime {

    private static final String NAME = "none";
    private static final NoneRuntime INSTANCE = new NoneRuntime();

    private NoneRuntime() {}

    public static NoneRuntime getInstance() {
      return INSTANCE;
    }

    @Override
    public String toString() {
      return NAME;
    }
  }

  // Wrapper for the DEX runtimes.
  public static class DexRuntime extends TestRuntime {

    private final DexVm vm;

    public DexRuntime(DexVm.Version version) {
      this(DexVm.fromVersion(version));
    }

    public DexRuntime(DexVm vm) {
      assert vm != null;
      this.vm = vm;
    }

    @Override
    public boolean isDex() {
      return true;
    }

    @Override
    public DexRuntime asDex() {
      return this;
    }

    public DexVm getVm() {
      return vm;
    }

    @Override
    public String toString() {
      return "dex-" + vm.getVersion().toString();
    }

    public AndroidApiLevel getMinApiLevel() {
      return ToolHelper.getMinApiLevelForDexVm(vm);
    }
  }

  // Wrapper for the CF runtimes.
  public static class CfRuntime extends TestRuntime {

    private final CfVm vm;

    public CfRuntime(CfVm vm) {
      assert vm != null;
      this.vm = vm;
    }

    @Override
    public boolean isCf() {
      return true;
    }

    @Override
    public CfRuntime asCf() {
      return this;
    }

    public CfVm getVm() {
      return vm;
    }

    @Override
    public String toString() {
      return vm.toString();
    }
  }

  public boolean isDex() {
    return false;
  }

  public boolean isCf() {
    return false;
  }

  public DexRuntime asDex() {
    return null;
  }

  public CfRuntime asCf() {
    return null;
  }

  public Backend getBackend() {
    if (isDex()) {
      return Backend.DEX;
    }
    if (isCf()) {
      return Backend.CF;
    }
    throw new Unreachable("Unexpected runtime without backend: " + this);
  }
}
