// 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, Compiler.dart2wasm],
      isBrowser: true, isBlink: true);

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

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

  /// Microsoft Internet Explorer.
  @Deprecated('Internet Explorer is no longer supported')
  static const Runtime internetExplorer = Runtime(
      'Internet Explorer', 'ie', Compiler.dart2js, [Compiler.dart2js],
      isBrowser: true);

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

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

  /// 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.edge,
    Runtime.nodeJS,
  ];

  /// 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 uses the Blink rendering engine.
  final bool isBlink;

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

  /// 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.isBlink = false,
      this.isHeadless = false})
      : parent = null;

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

  /// 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,
        isBlink: map['isBlink'] as bool,
        isHeadless: map['isHeadless'] 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,
      'isBlink': isBlink,
      'isHeadless': isHeadless,
      // TODO(https://github.com/dart-lang/test/issues/2146): Remove this.
      'isJS': isBrowser || this == Runtime.nodeJS,
      // TODO(https://github.com/dart-lang/test/issues/2146): Remove this.
      'isWasm': false,
    };
  }

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