// Copyright (c) 2015, the Dart 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.

import 'compiler.dart';

/// An enum of all Dart runtimes supported by the test runner.
final class Runtime {
  // When adding new runtimes, be sure to update the baseline and derived
  // variable tests in test/backend/platform_selector/evaluate_test.

  /// The command-line Dart VM.
  static const Runtime vm = Runtime('VM', 'vm', Compiler.kernel,
      [Compiler.kernel, Compiler.source, Compiler.exe],
      isDartVM: true);

  /// Google Chrome.
  static const Runtime chrome = Runtime(
      'Chrome', 'chrome', Compiler.dart2js, [Compiler.dart2js],
      isBrowser: true, isJS: true, isBlink: true);

  /// Mozilla Firefox.
  static const Runtime firefox = Runtime(
      'Firefox', 'firefox', Compiler.dart2js, [Compiler.dart2js],
      isBrowser: true, isJS: true);

  /// Apple Safari.
  static const Runtime safari = Runtime(
      'Safari', 'safari', Compiler.dart2js, [Compiler.dart2js],
      isBrowser: true, isJS: true);

  /// Microsoft Internet Explorer.
  static const Runtime internetExplorer = Runtime(
      'Internet Explorer', 'ie', Compiler.dart2js, [Compiler.dart2js],
      isBrowser: true, isJS: true);

  /// Microsoft Edge (based on Chromium).
  static const Runtime edge = Runtime(
      'Microsoft Edge', 'edge', Compiler.dart2js, [Compiler.dart2js],
      isBrowser: true, isJS: true, isBlink: true);

  /// The command-line Node.js VM.
  static const Runtime nodeJS = Runtime(
      'Node.js', 'node', Compiler.dart2js, [Compiler.dart2js],
      isJS: true);

  /// Google Chrome.
  static const Runtime experimentalChromeWasm = Runtime(
      'ExperimentalChromeWasm',
      'experimental-chrome-wasm',
      Compiler.dart2wasm,
      [Compiler.dart2wasm],
      isBrowser: true,
      isBlink: true,
      isWasm: true);

  /// The platforms that are supported by the test runner by default.
  static const List<Runtime> builtIn = [
    Runtime.vm,
    Runtime.chrome,
    Runtime.firefox,
    Runtime.safari,
    Runtime.internetExplorer,
    Runtime.edge,
    Runtime.nodeJS,
    Runtime.experimentalChromeWasm,
  ];

  /// The human-friendly name of the platform.
  final String name;

  /// The identifier used to look up the platform.
  final String identifier;

  /// The parent platform that this is based on, or `null` if there is no
  /// parent.
  final Runtime? parent;

  /// Returns whether this is a child of another platform.
  bool get isChild => parent != null;

  /// Whether this platform runs the Dart VM in any capacity.
  final bool isDartVM;

  /// Whether this platform is a browser.
  final bool isBrowser;

  /// Whether this platform runs Dart compiled to JavaScript.
  final bool isJS;

  /// Whether this platform uses the Blink rendering engine.
  final bool isBlink;

  /// Whether this platform has no visible window.
  final bool isHeadless;

  /// Whether this platform runs Dart compiled to WASM.
  final bool isWasm;

  /// Returns the platform this is based on, or [this] if it's not based on
  /// anything.
  ///
  /// That is, returns [parent] if it's non-`null` or [this] if it's `null`.
  Runtime get root => parent ?? this;

  /// The default compiler to use with this runtime.
  final Compiler defaultCompiler;

  /// All the supported compilers for this runtime.
  final List<Compiler> supportedCompilers;

  const Runtime(
      this.name, this.identifier, this.defaultCompiler, this.supportedCompilers,
      {this.isDartVM = false,
      this.isBrowser = false,
      this.isJS = false,
      this.isBlink = false,
      this.isHeadless = false,
      this.isWasm = false})
      : parent = null;

  Runtime._child(this.name, this.identifier, this.defaultCompiler,
      this.supportedCompilers, Runtime this.parent)
      : isDartVM = parent.isDartVM,
        isBrowser = parent.isBrowser,
        isJS = parent.isJS,
        isBlink = parent.isBlink,
        isHeadless = parent.isHeadless,
        isWasm = parent.isWasm;

  /// Converts a JSON-safe representation generated by [serialize] back into a
  /// [Runtime].
  factory Runtime.deserialize(Object serialized) {
    if (serialized is String) {
      return builtIn
          .firstWhere((platform) => platform.identifier == serialized);
    }

    var map = serialized as Map;
    var name = map['name'] as String;
    var identifier = map['identifier'] as String;
    var defaultCompiler =
        Compiler.deserialize(map['defaultCompiler'] as Object);
    var supportedCompilers = [
      for (var compiler in map['supportedCompilers'] as List)
        Compiler.deserialize(compiler as Object),
    ];

    var parent = map['parent'];
    if (parent != null) {
      // Note that the returned platform's [parent] won't necessarily be `==` to
      // a separately-deserialized parent platform. This should be fine, though,
      // since we only deserialize platforms in the remote execution context
      // where they're only used to evaluate platform selectors.
      return Runtime._child(name, identifier, defaultCompiler,
          supportedCompilers, Runtime.deserialize(parent as Object));
    }

    return Runtime(name, identifier, defaultCompiler, supportedCompilers,
        isDartVM: map['isDartVM'] as bool,
        isBrowser: map['isBrowser'] as bool,
        isJS: map['isJS'] as bool,
        isBlink: map['isBlink'] as bool,
        isHeadless: map['isHeadless'] as bool,
        isWasm: map['isWasm'] as bool);
  }

  /// Converts [this] into a JSON-safe object that can be converted back to a
  /// [Runtime] using [Runtime.deserialize].
  Object serialize() {
    if (builtIn.contains(this)) return identifier;

    if (parent != null) {
      return {
        'name': name,
        'defaultCompiler': defaultCompiler.serialize(),
        'supportedCompilers': [
          for (var compiler in supportedCompilers) compiler.serialize(),
        ],
        'identifier': identifier,
        'parent': parent!.serialize()
      };
    }

    return {
      'name': name,
      'defaultCompiler': defaultCompiler.serialize(),
      'supportedCompilers': [
        for (var compiler in supportedCompilers) compiler.serialize(),
      ],
      'identifier': identifier,
      'isDartVM': isDartVM,
      'isBrowser': isBrowser,
      'isJS': isJS,
      'isBlink': isBlink,
      'isHeadless': isHeadless,
      'isWasm': isWasm,
    };
  }

  /// Returns a child of [this] that counts as both this platform's identifier
  /// and the new [identifier].
  ///
  /// This may not be called on a platform that's already a child.
  Runtime extend(String name, String identifier) {
    if (parent == null) {
      return Runtime._child(
          name, identifier, defaultCompiler, supportedCompilers, this);
    }
    throw StateError('A child platform may not be extended.');
  }

  @override
  String toString() => name;
}
