// 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);
  static const Runtime vmAsan = Runtime(
    'VM with Address Sanitizer',
    'vm-asan',
    Compiler.exe,
    [Compiler.exe],
    isDartVM: true,
  );
  static const Runtime vmMsan = Runtime(
    'VM with Memory Sanitizer',
    'vm-msan',
    Compiler.exe,
    [Compiler.exe],
    isDartVM: true,
  );
  static const Runtime vmTsan = Runtime(
    'VM with Thread Sanitizer',
    'vm-tsan',
    Compiler.exe,
    [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.vmAsan,
    Runtime.vmMsan,
    Runtime.vmTsan,
    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;
}
