// Copyright (c) 2017, 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 'dart:async';
// We need to use the 'io' prefix here, otherwise io.exitCode will shadow
// CommandOutput.exitCode in subclasses of CommandOutput.
import 'dart:io' as io;

import 'command_output.dart';
import 'configuration.dart';
import 'path.dart';
import 'test_case.dart';
import 'utils.dart';

/// A command executed as a step in a test case.
abstract class Command {
  /// A descriptive name for this command.
  final String displayName;

  /// When cloning a command object to run it multiple times, we give
  /// the different copies distinct values for index.
  final int index;

  /// Number of times this command *can* be retried.
  int get maxNumRetries => 2;

  /// Reproduction command.
  String get reproductionCommand;

  /// We compute the Command.hashCode lazily and cache it here, since it might
  /// be expensive to compute (and hashCode is called often).
  int? _cachedHashCode;

  Command._(this.displayName, {this.index = 0});

  /// A virtual clone method for a member of the Command hierarchy.
  /// Two clones with the same index will be equal, with different indices
  /// will be distinct. Used to run tests multiple times, since identical
  /// commands are only run once by the dependency graph scheduler.
  Command indexedCopy(int index);

  CommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int pid = 0,
  ]) => CommandOutput(
    this,
    exitCode,
    timedOut,
    stdout,
    stderr,
    time,
    compilationSkipped,
    pid,
  );

  @override
  int get hashCode {
    if (_cachedHashCode == null) {
      var builder = HashCodeBuilder();
      _buildHashCode(builder);
      _cachedHashCode = builder.value;
    }
    return _cachedHashCode!;
  }

  @override
  operator ==(Object other) =>
      identical(this, other) ||
      (runtimeType == other.runtimeType && _equal(other as Command));

  void _buildHashCode(HashCodeBuilder builder) {
    builder.add(displayName);
    builder.add(index);
  }

  bool _equal(covariant Command other) =>
      hashCode == other.hashCode &&
      displayName == other.displayName &&
      index == other.index;

  @override
  String toString() => reproductionCommand;

  bool get outputIsUpToDate => false;
}

class ProcessCommand extends Command {
  /// Path to the executable of this command.
  String executable;

  /// Command line arguments to the executable.
  final List<String> arguments;

  /// Environment for the command.
  final Map<String, String> environmentOverrides;

  /// Working directory for the command.
  final String? workingDirectory;

  ProcessCommand(
    super.displayName,
    this.executable,
    this.arguments, [
    this.environmentOverrides = const {},
    this.workingDirectory,
    int index = 0,
  ]) : super._(index: index) {
    if (io.Platform.operatingSystem == 'windows') {
      // Windows can't handle the first command if it is a .bat file or the like
      // with the slashes going the other direction.
      // NOTE: Issue 1306
      executable = executable.replaceAll('/', '\\');
    }
  }

  @override
  ProcessCommand indexedCopy(int index) {
    return ProcessCommand(
      displayName,
      executable,
      arguments,
      environmentOverrides,
      workingDirectory,
      index,
    );
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(executable);
    builder.addJson(workingDirectory);
    builder.addJson(arguments);
    builder.addJson(environmentOverrides);
  }

  @override
  bool _equal(ProcessCommand other) =>
      super._equal(other) &&
      executable == other.executable &&
      deepJsonCompare(arguments, other.arguments) &&
      workingDirectory == other.workingDirectory &&
      deepJsonCompare(environmentOverrides, other.environmentOverrides);

  @override
  String get reproductionCommand {
    var env = StringBuffer();
    environmentOverrides.forEach(
      (key, value) => (io.Platform.operatingSystem == 'windows')
          ? env.write('set $key=${escapeCommandLineArgument(value)} & ')
          : env.write('$key=${escapeCommandLineArgument(value)} '),
    );
    var command = [
      executable,
      ...nonBatchArguments,
      ...arguments,
    ].map(escapeCommandLineArgument).join(' ');
    if (workingDirectory != null) {
      command = "$command (working directory: $workingDirectory)";
    }
    return "$env$command";
  }

  @override
  bool get outputIsUpToDate => false;

  /// Additional arguments to prepend before [arguments] when running the
  /// process in batch mode.
  List<String> get batchArguments => const [];

  /// Additional arguments to prepend before [arguments] when running the
  /// process in non-batch mode.
  List<String> get nonBatchArguments => const [];
}

class CompilationCommand extends ProcessCommand {
  /// The primary output file that will be created by this command.
  final String outputFile;

  /// If true, then the compilation is run even if the input files are older
  /// than the output file.
  final bool _alwaysCompile;
  final List<Uri> _bootstrapDependencies;

  CompilationCommand(
    String displayName,
    this.outputFile,
    this._bootstrapDependencies,
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides, {
    required this._alwaysCompile,
    String? workingDirectory,
    int index = 0,
  }) : super(
         displayName,
         executable,
         arguments,
         environmentOverrides,
         workingDirectory,
         index,
       );

  @override
  CompilationCommand indexedCopy(int index) => CompilationCommand(
    displayName,
    outputFile,
    _bootstrapDependencies,
    executable,
    arguments,
    environmentOverrides,
    alwaysCompile: _alwaysCompile,
    workingDirectory: workingDirectory,
    index: index,
  );

  @override
  CommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int pid = 0,
  ]) {
    if (displayName == 'precompiler' ||
        displayName == 'app_jit' ||
        displayName == 'dart2bytecode' ||
        displayName == 'modaot') {
      return VMCommandOutput(
        this,
        exitCode,
        timedOut,
        stdout,
        stderr,
        time,
        pid,
      );
    } else if (displayName == 'dart2wasm') {
      return Dart2WasmCompilerCommandOutput(
        this,
        exitCode,
        timedOut,
        stdout,
        stderr,
        time,
        compilationSkipped,
      );
    }

    return CompilationCommandOutput(
      this,
      exitCode,
      timedOut,
      stdout,
      stderr,
      time,
      compilationSkipped,
    );
  }

  @override
  bool get outputIsUpToDate {
    if (_alwaysCompile) return false;

    var file = io.File(Path("$outputFile.deps").toNativePath());
    if (!file.existsSync()) return false;

    var lines = file.readAsLinesSync();
    var dependencies = <Uri>[];
    for (var line in lines) {
      line = line.trim();
      if (line.isNotEmpty) {
        dependencies.add(Uri.parse(line));
      }
    }

    dependencies.addAll(_bootstrapDependencies);
    var jsOutputLastModified = TestUtils.lastModifiedCache.getLastModified(
      Uri(scheme: 'file', path: outputFile),
    );
    if (jsOutputLastModified == null) return false;

    for (var dependency in dependencies) {
      var dependencyLastModified = TestUtils.lastModifiedCache.getLastModified(
        dependency,
      );
      if (dependencyLastModified == null ||
          dependencyLastModified.isAfter(jsOutputLastModified)) {
        return false;
      }
    }
    return true;
  }

  @override
  List<String> get batchArguments {
    return [...arguments.where((arg) => arg.startsWith('--enable-experiment'))];
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(outputFile);
    builder.addJson(_alwaysCompile);
    builder.addJson(_bootstrapDependencies);
  }

  @override
  bool _equal(CompilationCommand other) =>
      super._equal(other) &&
      outputFile == other.outputFile &&
      _alwaysCompile == other._alwaysCompile &&
      deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
}

class Dart2jsCompilationCommand extends CompilationCommand {
  final bool useSdk;

  Dart2jsCompilationCommand(
    String outputFile,
    List<Uri> bootstrapDependencies,
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides, {
    required this.useSdk,
    required super.alwaysCompile,
    super.workingDirectory,
    super.index = 0,
  }) : super(
         "dart2js",
         outputFile,
         bootstrapDependencies,
         executable,
         arguments,
         environmentOverrides,
       );

  @override
  Dart2jsCompilationCommand indexedCopy(int index) => Dart2jsCompilationCommand(
    outputFile,
    _bootstrapDependencies,
    executable,
    arguments,
    environmentOverrides,
    useSdk: useSdk,
    alwaysCompile: _alwaysCompile,
    workingDirectory: workingDirectory,
    index: index,
  );

  @override
  CommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) {
    return Dart2jsCompilerCommandOutput(
      this,
      exitCode,
      timedOut,
      stdout,
      stderr,
      time,
      compilationSkipped,
    );
  }

  @override
  List<String> get batchArguments {
    return <String>[
      if (useSdk) ...['compile', 'js'],
      ...super.batchArguments,
    ];
  }

  @override
  List<String> get nonBatchArguments {
    return <String>[
      if (useSdk) ...['compile', 'js'],
      ...super.nonBatchArguments,
    ];
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(useSdk);
  }

  @override
  bool _equal(Dart2jsCompilationCommand other) {
    return super._equal(other) && useSdk == other.useSdk;
  }
}

class DevCompilerCompilationCommand extends CompilationCommand {
  final String compilerPath;

  final bool enableHostAsserts;

  DevCompilerCompilationCommand(
    String outputFile,
    List<Uri> bootstrapDependencies,
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides, {
    required this.compilerPath,
    required super.alwaysCompile,
    required this.enableHostAsserts,
    super.workingDirectory,
    super.index = 0,
  }) : super(
         "ddc",
         outputFile,
         bootstrapDependencies,
         executable,
         arguments,
         environmentOverrides,
       );

  @override
  DevCompilerCompilationCommand indexedCopy(int index) =>
      DevCompilerCompilationCommand(
        outputFile,
        _bootstrapDependencies,
        executable,
        arguments,
        environmentOverrides,
        compilerPath: compilerPath,
        alwaysCompile: _alwaysCompile,
        enableHostAsserts: enableHostAsserts,
        workingDirectory: workingDirectory,
        index: index,
      );

  @override
  CommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int pid = 0,
  ]) {
    return DevCompilerCommandOutput(
      this,
      exitCode,
      timedOut,
      stdout,
      stderr,
      time,
      compilationSkipped,
      pid,
    );
  }

  @override
  List<String> get batchArguments {
    return <String>[
      if (enableHostAsserts) '--enable-asserts',
      compilerPath,
      ...super.batchArguments,
    ];
  }

  @override
  List<String> get nonBatchArguments {
    return <String>[
      if (enableHostAsserts) '--enable-asserts',
      compilerPath,
      ...super.nonBatchArguments,
    ];
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(compilerPath);
  }

  @override
  bool _equal(DevCompilerCompilationCommand other) {
    return super._equal(other) && compilerPath == other.compilerPath;
  }
}

class FastaCompilationCommand extends CompilationCommand {
  final Uri _compilerLocation;

  FastaCompilationCommand(
    this._compilerLocation,
    String outputFile,
    List<Uri> bootstrapDependencies,
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides,
    String? workingDirectory, {
    super.index = 0,
  }) : super(
         "fasta",
         outputFile,
         bootstrapDependencies,
         executable,
         arguments,
         environmentOverrides,
         alwaysCompile: true,
         workingDirectory: workingDirectory,
       );

  @override
  FastaCompilationCommand indexedCopy(int index) => FastaCompilationCommand(
    _compilerLocation,
    outputFile,
    _bootstrapDependencies,
    executable,
    arguments,
    environmentOverrides,
    workingDirectory,
    index: index,
  );

  @override
  FastaCommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) => FastaCommandOutput(
    this,
    exitCode,
    timedOut,
    stdout,
    stderr,
    time,
    compilationSkipped,
  );

  @override
  List<String> get batchArguments {
    return <String>[
      ...super.batchArguments,
      '--enable-asserts',
      _compilerLocation.resolve("batch.dart").toFilePath(),
    ];
  }

  @override
  String get reproductionCommand {
    String relativizeAndEscape(String argument) {
      if (workingDirectory != null) {
        argument = argument.replaceAll(
          workingDirectory!,
          Uri.directory(".").toFilePath(),
        );
      }
      return escapeCommandLineArgument(argument);
    }

    var buffer = StringBuffer();
    if (workingDirectory != null && !io.Platform.isWindows) {
      buffer.write("(cd ");
      buffer.write(escapeCommandLineArgument(workingDirectory!));
      buffer.write(" ; ");
    }
    environmentOverrides.forEach((key, value) {
      if (io.Platform.isWindows) {
        buffer.write("set ");
      }
      buffer.write(key);
      buffer.write("=");
      buffer.write(relativizeAndEscape(value));
      if (io.Platform.isWindows) {
        buffer.write(" &");
      }
      buffer.write(" ");
    });
    buffer.writeAll(
      [
        executable,
        _compilerLocation.toFilePath(),
        ...arguments,
      ].map(relativizeAndEscape),
      " ",
    );
    if (workingDirectory != null) {
      if (io.Platform.isWindows) {
        buffer.write(" (working directory: $workingDirectory)");
      } else {
        buffer.write(" )");
      }
    }
    return "$buffer";
  }

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(_compilerLocation);
  }

  @override
  bool _equal(FastaCompilationCommand other) {
    return super._equal(other) && _compilerLocation == other._compilerLocation;
  }
}

class VMKernelCompilationCommand extends CompilationCommand {
  VMKernelCompilationCommand(
    String outputFile,
    List<Uri> bootstrapDependencies,
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides, {
    required super.alwaysCompile,
    super.index = 0,
  }) : super(
         'vm_compile_to_kernel',
         outputFile,
         bootstrapDependencies,
         executable,
         arguments,
         environmentOverrides,
       );

  @override
  VMKernelCompilationCommand indexedCopy(int index) =>
      VMKernelCompilationCommand(
        outputFile,
        _bootstrapDependencies,
        executable,
        arguments,
        environmentOverrides,
        alwaysCompile: _alwaysCompile,
        index: index,
      );

  @override
  VMKernelCompilationCommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) => VMKernelCompilationCommandOutput(
    this,
    exitCode,
    timedOut,
    stdout,
    stderr,
    time,
    compilationSkipped,
  );

  @override
  int get maxNumRetries => 1;
}

/// This is just a Pair(String, Map) class with hashCode and operator ==
class AddFlagsKey {
  final String flags;
  final Map env;
  AddFlagsKey(this.flags, this.env);
  // Just use object identity for environment map
  @override
  bool operator ==(Object other) =>
      other is AddFlagsKey && flags == other.flags && env == other.env;
  @override
  int get hashCode => flags.hashCode ^ env.hashCode;
}

class BrowserTestCommand extends Command {
  Runtime get browser => configuration.runtime;
  final String url;
  final TestConfiguration configuration;

  BrowserTestCommand(this.url, this.configuration, {super.index = 0})
    : super._(configuration.runtime.name);

  @override
  BrowserTestCommand indexedCopy(int index) =>
      BrowserTestCommand(url, configuration, index: index);

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.addJson(browser.name);
    builder.addJson(url);
    builder.add(configuration);
  }

  @override
  bool _equal(BrowserTestCommand other) =>
      super._equal(other) &&
      browser == other.browser &&
      url == other.url &&
      identical(configuration, other.configuration);

  @override
  String get reproductionCommand {
    var parts = [
      io.Platform.resolvedExecutable,
      'pkg/test_runner/bin/launch_browser.dart',
      browser.name,
      url,
    ];
    return parts.map(escapeCommandLineArgument).join(' ');
  }

  @override
  int get maxNumRetries => 4;
}

class AnalysisCommand extends ProcessCommand {
  final List<String> commonAnalyzerCliArguments;

  AnalysisCommand(
    String executable,
    List<String> arguments,
    this.commonAnalyzerCliArguments,
    Map<String, String> environmentOverrides, {
    int index = 0,
  }) : super(
         'dart2analyzer',
         executable,
         arguments,
         environmentOverrides,
         null,
         index,
       );

  @override
  AnalysisCommand indexedCopy(int index) => AnalysisCommand(
    executable,
    arguments,
    commonAnalyzerCliArguments,
    environmentOverrides,
    index: index,
  );

  @override
  CommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) => AnalysisCommandOutput(
    this,
    exitCode,
    timedOut,
    stdout,
    stderr,
    time,
    compilationSkipped,
  );

  @override
  List<String> get batchArguments => commonAnalyzerCliArguments;

  @override
  List<String> get nonBatchArguments => commonAnalyzerCliArguments;

  @override
  bool _equal(covariant ProcessCommand other) {
    return other is AnalysisCommand &&
        super._equal(other) &&
        deepJsonCompare(
          commonAnalyzerCliArguments,
          other.commonAnalyzerCliArguments,
        );
  }
}

class CompareAnalyzerCfeCommand extends ProcessCommand {
  CompareAnalyzerCfeCommand(
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides, {
    int index = 0,
  }) : super(
         'compare_analyzer_cfe',
         executable,
         arguments,
         environmentOverrides,
         null,
         index,
       );

  @override
  CompareAnalyzerCfeCommand indexedCopy(int index) => CompareAnalyzerCfeCommand(
    executable,
    arguments,
    environmentOverrides,
    index: index,
  );

  @override
  CompareAnalyzerCfeCommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) => CompareAnalyzerCfeCommandOutput(
    this,
    exitCode,
    timedOut,
    stdout,
    stderr,
    time,
    compilationSkipped,
  );
}

class SpecParseCommand extends ProcessCommand {
  SpecParseCommand(
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides, {
    int index = 0,
  }) : super(
         'spec_parser',
         executable,
         arguments,
         environmentOverrides,
         null,
         index,
       );

  @override
  SpecParseCommand indexedCopy(int index) => SpecParseCommand(
    executable,
    arguments,
    environmentOverrides,
    index: index,
  );

  @override
  SpecParseCommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) => SpecParseCommandOutput(
    this,
    exitCode,
    timedOut,
    stdout,
    stderr,
    time,
    compilationSkipped,
  );
}

class VMCommand extends ProcessCommand {
  VMCommand(
    String executable,
    List<String> arguments,
    Map<String, String> environmentOverrides, {
    int index = 0,
  }) : super('vm', executable, arguments, environmentOverrides, null, index);

  @override
  VMCommand indexedCopy(int index) =>
      VMCommand(executable, arguments, environmentOverrides, index: index);

  @override
  CommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int pid = 0,
  ]) => VMCommandOutput(this, exitCode, timedOut, stdout, stderr, time, pid);
}

// Run a VM test under RR, and copy the trace if it crashes. Using a helper
// script like the precompiler does not work because the RR traces are large
// and we must diligently erase them for non-crashes even if the test times
// out and would be killed by the harness, so the copying and cleanup logic
// must be in the harness.
class RRCommand extends Command {
  ProcessCommand originalCommand;
  late ProcessCommand wrappedCommand;
  late io.Directory recordingDir;
  late io.Directory savedDir;

  RRCommand(this.originalCommand)
    : super._(originalCommand.displayName, index: originalCommand.index) {
    final suffix = "/rr-trace-${originalCommand.hashCode}";
    recordingDir = io.Directory(io.Directory.systemTemp.path + suffix);
    savedDir = io.Directory("out$suffix");
    final executable = "rr";
    final arguments = <String>[
      "record",
      "--chaos",
      "--output-trace-dir=${recordingDir.path}",
    ];
    arguments.add(originalCommand.executable);
    arguments.addAll(originalCommand.nonBatchArguments);
    arguments.addAll(originalCommand.arguments);
    wrappedCommand = ProcessCommand(
      originalCommand.displayName,
      executable,
      arguments,
      originalCommand.environmentOverrides,
      originalCommand.workingDirectory,
      originalCommand.index,
    );
  }

  @override
  RRCommand indexedCopy(int index) =>
      RRCommand(originalCommand.indexedCopy(index));

  Future<CommandOutput> run(
    int timeout,
    TestConfiguration configuration,
  ) async {
    // rr will fail if the output trace directory already exists. Delete any
    // that might be leftover from interrupting the harness.
    if (await recordingDir.exists()) {
      await recordingDir.delete(recursive: true);
    }
    final output = await RunningProcess(
      wrappedCommand,
      timeout,
      configuration: configuration,
    ).run();
    if (output.hasCrashed) {
      if (await savedDir.exists()) {
        await savedDir.delete(recursive: true);
      }
      await recordingDir.rename(savedDir.path);
      await io.File(
        "${savedDir.path}/command.txt",
      ).writeAsString(wrappedCommand.reproductionCommand);
      await io.File("${savedDir.path}/stdout.txt").writeAsBytes(output.stdout);
      await io.File("${savedDir.path}/stderr.txt").writeAsBytes(output.stderr);
    } else if (await recordingDir.exists()) {
      await recordingDir.delete(recursive: true);
    }

    final compilationSkipped = false;
    switch (displayName) {
      case 'app_jit':
      case 'precompiler':
      case 'run_vm_unittest':
      case 'vm':
        return VMCommandOutput(
          this,
          output.exitCode,
          output.hasTimedOut,
          output.stdout,
          output.stderr,
          output.time,
          output.pid,
        );
      case 'dart2wasm':
        return Dart2WasmCompilerCommandOutput(
          this,
          output.exitCode,
          output.hasTimedOut,
          output.stdout,
          output.stderr,
          output.time,
          compilationSkipped,
        );
      case 'dart2js':
        return Dart2jsCompilerCommandOutput(
          this,
          output.exitCode,
          output.hasTimedOut,
          output.stdout,
          output.stderr,
          output.time,
          compilationSkipped,
        );
      case 'ddc':
        return DevCompilerCommandOutput(
          this,
          output.exitCode,
          output.hasTimedOut,
          output.stdout,
          output.stderr,
          output.time,
          compilationSkipped,
          output.pid,
        );
    }
    throw "Don't know how to interpret output for $displayName";
  }

  @override
  String get reproductionCommand =>
      "${wrappedCommand.reproductionCommand} (rr replay ${savedDir.path})";

  @override
  void _buildHashCode(HashCodeBuilder builder) {
    originalCommand._buildHashCode(builder);
    builder.add(42);
  }

  @override
  bool _equal(RRCommand other) =>
      hashCode == other.hashCode &&
      originalCommand._equal(other.originalCommand);
}

abstract class AdbCommand {
  String get buildPath;
  List<String> get extraLibraries;
}

class AdbPrecompilationCommand extends Command implements AdbCommand {
  @override
  final String buildPath; // Path to the output directory of the build.
  final String processTestFilename;
  final String abstractSocketTestFilename;
  final String precompiledTestDirectory;
  final List<String> arguments;
  final bool useElf;
  @override
  final List<String> extraLibraries;

  AdbPrecompilationCommand(
    this.buildPath,
    this.processTestFilename,
    this.abstractSocketTestFilename,
    this.precompiledTestDirectory,
    this.arguments,
    this.useElf,
    this.extraLibraries, {
    super.index = 0,
  }) : super._("adb_precompilation");

  @override
  AdbPrecompilationCommand indexedCopy(int index) => AdbPrecompilationCommand(
    buildPath,
    processTestFilename,
    abstractSocketTestFilename,
    precompiledTestDirectory,
    arguments,
    useElf,
    extraLibraries,
    index: index,
  );

  @override
  VMCommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int pid = 0,
  ]) => VMCommandOutput(this, exitCode, timedOut, stdout, stderr, time, pid);

  @override
  _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.add(buildPath);
    builder.add(precompiledTestDirectory);
    builder.add(arguments);
    builder.add(useElf);
    extraLibraries.forEach(builder.add);
  }

  @override
  bool _equal(AdbPrecompilationCommand other) =>
      super._equal(other) &&
      buildPath == other.buildPath &&
      useElf == other.useElf &&
      arguments == other.arguments &&
      precompiledTestDirectory == other.precompiledTestDirectory &&
      deepJsonCompare(extraLibraries, other.extraLibraries);

  @override
  String toString() =>
      'Steps to push precompiled runner and precompiled code '
      'to an attached device. Uses (and requires) adb.';

  @override
  String get reproductionCommand => throw UnimplementedError();
}

class AdbDartkCommand extends Command implements AdbCommand {
  @override
  final String buildPath;
  final String processTestFilename;
  final String abstractSocketTestFilename;
  final String kernelFile;
  final List<String> arguments;
  @override
  final List<String> extraLibraries;

  AdbDartkCommand(
    this.buildPath,
    this.processTestFilename,
    this.abstractSocketTestFilename,
    this.kernelFile,
    this.arguments,
    this.extraLibraries, {
    super.index = 0,
  }) : super._("adb_precompilation");

  @override
  AdbDartkCommand indexedCopy(int index) => AdbDartkCommand(
    buildPath,
    processTestFilename,
    abstractSocketTestFilename,
    kernelFile,
    arguments,
    extraLibraries,
    index: index,
  );

  @override
  _buildHashCode(HashCodeBuilder builder) {
    super._buildHashCode(builder);
    builder.add(buildPath);
    builder.add(kernelFile);
    builder.add(arguments);
    builder.add(extraLibraries);
  }

  @override
  bool _equal(AdbDartkCommand other) =>
      super._equal(other) &&
      buildPath == other.buildPath &&
      arguments == other.arguments &&
      extraLibraries == other.extraLibraries &&
      kernelFile == other.kernelFile;

  @override
  VMCommandOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int pid = 0,
  ]) => VMCommandOutput(this, exitCode, timedOut, stdout, stderr, time, pid);

  @override
  String toString() =>
      'Steps to push Dart VM and Dill file '
      'to an attached device. Uses (and requires) adb.';

  @override
  String get reproductionCommand => throw UnimplementedError();
}

class JSCommandLineCommand extends ProcessCommand {
  JSCommandLineCommand(
    String displayName,
    String executable,
    List<String> arguments, [
    Map<String, String> environmentOverrides = const {},
    int index = 0,
  ]) : super(
         displayName,
         executable,
         arguments,
         environmentOverrides,
         null,
         index,
       );

  @override
  JSCommandLineCommand indexedCopy(int index) => JSCommandLineCommand(
    displayName,
    executable,
    arguments,
    environmentOverrides,
    index,
  );

  @override
  JSCommandLineOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) => JSCommandLineOutput(this, exitCode, timedOut, stdout, stderr, time);
}

class Dart2WasmCommandLineCommand extends ProcessCommand {
  Dart2WasmCommandLineCommand(
    String displayName,
    String executable,
    List<String> arguments, [
    Map<String, String> environmentOverrides = const {},
    int index = 0,
  ]) : super(
         displayName,
         executable,
         arguments,
         environmentOverrides,
         null,
         index,
       );

  @override
  Dart2WasmCommandLineCommand indexedCopy(int index) =>
      Dart2WasmCommandLineCommand(
        displayName,
        executable,
        arguments,
        environmentOverrides,
        index,
      );

  @override
  Dart2WasmCommandLineOutput createOutput(
    int exitCode,
    bool timedOut,
    List<int> stdout,
    List<int> stderr,
    Duration time,
    bool compilationSkipped, [
    int? pid = 0,
  ]) => Dart2WasmCommandLineOutput(
    this,
    exitCode,
    timedOut,
    stdout,
    stderr,
    time,
  );
}

/// [ScriptCommand]s are executed by dart code.
abstract class ScriptCommand extends Command {
  ScriptCommand._(super.displayName) : super._();

  Future<ScriptCommandOutput> run();
}
