// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @dart = 2.8

import 'dart:async';
import 'dart:convert';
import 'dart:io' as io show ProcessSignal, Process, ProcessStartMode, ProcessResult, systemEncoding;

import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';

import 'test_wrapper.dart';

export 'package:process/process.dart' show ProcessManager;

typedef VoidCallback = void Function();

/// A command for [FakeProcessManager].
@immutable
class FakeCommand {
  const FakeCommand({
    @required this.command,
    this.workingDirectory,
    this.environment,
    this.encoding,
    this.duration = Duration.zero,
    this.onRun,
    this.exitCode = 0,
    this.stdout = '',
    this.stderr = '',
    this.completer,
    this.stdin,
    this.exception,
  }) : assert(command != null),
       assert(duration != null),
       assert(exitCode != null);

  /// The exact commands that must be matched for this [FakeCommand] to be
  /// considered correct.
  final List<String> command;

  /// The exact working directory that must be matched for this [FakeCommand] to
  /// be considered correct.
  ///
  /// If this is null, the working directory is ignored.
  final String workingDirectory;

  /// The environment that must be matched for this [FakeCommand] to be considered correct.
  ///
  /// If this is null, then the environment is ignored.
  ///
  /// Otherwise, each key in this environment must be present and must have a
  /// value that matches the one given here for the [FakeCommand] to match.
  final Map<String, String> environment;

  /// The stdout and stderr encoding that must be matched for this [FakeCommand]
  /// to be considered correct.
  ///
  /// If this is null, then the encodings are ignored.
  final Encoding encoding;

  /// The time to allow to elapse before returning the [exitCode], if this command
  /// is "executed".
  ///
  /// If you set this to a non-zero time, you should use a [FakeAsync] zone,
  /// otherwise the test will be artificially slow.
  final Duration duration;

  /// A callback that is run after [duration] expires but before the [exitCode]
  /// (and output) are passed back.
  final VoidCallback onRun;

  /// The process' exit code.
  ///
  /// To simulate a never-ending process, set [duration] to a value greater than
  /// 15 minutes (the timeout for our tests).
  ///
  /// To simulate a crash, subtract the crash signal number from 256. For example,
  /// SIGPIPE (-13) is 243.
  final int exitCode;

  /// The output to simulate on stdout. This will be encoded as UTF-8 and
  /// returned in one go.
  final String stdout;

  /// The output to simulate on stderr. This will be encoded as UTF-8 and
  /// returned in one go.
  final String stderr;

  /// If provided, allows the command completion to be blocked until the future
  /// resolves.
  final Completer<void> completer;

  /// An optional stdin sink that will be exposed through the resulting
  /// [FakeProcess].
  final IOSink stdin;

  /// If provided, this exception will be thrown when the fake command is run.
  final dynamic exception;

  void _matches(
    List<String> command,
    String workingDirectory,
    Map<String, String> environment,
    Encoding encoding,
  ) {
    expect(command, equals(this.command));
    if (this.workingDirectory != null) {
      expect(this.workingDirectory, workingDirectory);
    }
    if (this.environment != null) {
      expect(this.environment, environment);
    }
    if (this.encoding != null) {
      expect(this.encoding, encoding);
    }
  }
}

class _FakeProcess implements io.Process {
  _FakeProcess(
    this._exitCode,
    Duration duration,
    this.pid,
    this._stderr,
    this.stdin,
    this._stdout,
    this._completer,
  ) : exitCode = Future<void>.delayed(duration).then((void value) {
        if (_completer != null) {
          return _completer.future.then((void _) => _exitCode);
        }
        return _exitCode;
      }),
      stderr = _stderr == null
        ? const Stream<List<int>>.empty()
        : Stream<List<int>>.value(utf8.encode(_stderr)),
      stdout = _stdout == null
        ? const Stream<List<int>>.empty()
        : Stream<List<int>>.value(utf8.encode(_stdout));

  final int _exitCode;
  final Completer<void> _completer;

  @override
  final Future<int> exitCode;

  @override
  final int pid;

  final String _stderr;

  @override
  final Stream<List<int>> stderr;

  @override
  final IOSink stdin;

  @override
  final Stream<List<int>> stdout;

  final String _stdout;

  @override
  bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
    // Killing a fake process has no effect.
    return false;
  }
}

abstract class FakeProcessManager implements ProcessManager {
  /// A fake [ProcessManager] which responds to all commands as if they had run
  /// instantaneously with an exit code of 0 and no output.
  factory FakeProcessManager.any() = _FakeAnyProcessManager;

  /// A fake [ProcessManager] which responds to particular commands with
  /// particular results.
  ///
  /// On creation, pass in a list of [FakeCommand] objects. When the
  /// [ProcessManager] methods such as [start] are invoked, the next
  /// [FakeCommand] must match (otherwise the test fails); its settings are used
  /// to simulate the result of running that command.
  ///
  /// If no command is found, then one is implied which immediately returns exit
  /// code 0 with no output.
  ///
  /// There is no logic to ensure that all the listed commands are run. Use
  /// [FakeCommand.onRun] to set a flag, or specify a sentinel command as your
  /// last command and verify its execution is successful, to ensure that all
  /// the specified commands are actually called.
  factory FakeProcessManager.list(List<FakeCommand> commands) = _SequenceProcessManager;

  FakeProcessManager._();

  /// Adds a new [FakeCommand] to the current process manager.
  ///
  /// This can be used to configure test expectations after the [ProcessManager] has been
  /// provided to another interface.
  ///
  /// This is a no-op on [FakeProcessManager.any].
  void addCommand(FakeCommand command);

  /// Add multiple [FakeCommand] to the current process manager.
  void addCommands(Iterable<FakeCommand> commands) {
    commands.forEach(addCommand);
  }

  final Map<int, _FakeProcess> _fakeRunningProcesses = <int, _FakeProcess>{};

  /// Whether this fake has more [FakeCommand]s that are expected to run.
  ///
  /// This is always `true` for [FakeProcessManager.any].
  bool get hasRemainingExpectations;

  /// The expected [FakeCommand]s that have not yet run.
  List<FakeCommand> get _remainingExpectations;

  @protected
  FakeCommand findCommand(
    List<String> command,
    String workingDirectory,
    Map<String, String> environment,
    Encoding encoding,
  );

  int _pid = 9999;

  _FakeProcess _runCommand(
    List<String> command,
    String workingDirectory,
    Map<String, String> environment,
    Encoding encoding,
  ) {
    _pid += 1;
    final FakeCommand fakeCommand = findCommand(command, workingDirectory, environment, encoding);
    if (fakeCommand.exception != null) {
      throw fakeCommand.exception;
    }
    if (fakeCommand.onRun != null) {
      fakeCommand.onRun();
    }
    return _FakeProcess(
      fakeCommand.exitCode,
      fakeCommand.duration,
      _pid,
      fakeCommand.stderr,
      fakeCommand.stdin,
      fakeCommand.stdout,
      fakeCommand.completer,
    );
  }

  @override
  Future<io.Process> start(
    List<dynamic> command, {
    String workingDirectory,
    Map<String, String> environment,
    bool includeParentEnvironment = true, // ignored
    bool runInShell = false, // ignored
    io.ProcessStartMode mode = io.ProcessStartMode.normal, // ignored
  }) {
    final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment, io.systemEncoding);
    if (process._completer != null) {
      _fakeRunningProcesses[process.pid] = process;
      process.exitCode.whenComplete(() {
        _fakeRunningProcesses.remove(process.pid);
      });
    }
    return Future<io.Process>.value(process);
  }

  @override
  Future<io.ProcessResult> run(
    List<dynamic> command, {
    String workingDirectory,
    Map<String, String> environment,
    bool includeParentEnvironment = true, // ignored
    bool runInShell = false, // ignored
    Encoding stdoutEncoding = io.systemEncoding,
    Encoding stderrEncoding = io.systemEncoding,
  }) async {
    final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment, stdoutEncoding);
    await process.exitCode;
    return io.ProcessResult(
      process.pid,
      process._exitCode,
      stdoutEncoding == null ? process.stdout : await stdoutEncoding.decodeStream(process.stdout),
      stderrEncoding == null ? process.stderr : await stderrEncoding.decodeStream(process.stderr),
    );
  }

  @override
  io.ProcessResult runSync(
    List<dynamic> command, {
    String workingDirectory,
    Map<String, String> environment,
    bool includeParentEnvironment = true, // ignored
    bool runInShell = false, // ignored
    Encoding stdoutEncoding = io.systemEncoding, // actual encoder is ignored
    Encoding stderrEncoding = io.systemEncoding, // actual encoder is ignored
  }) {
    final _FakeProcess process = _runCommand(command.cast<String>(), workingDirectory, environment, stdoutEncoding);
    return io.ProcessResult(
      process.pid,
      process._exitCode,
      stdoutEncoding == null ? utf8.encode(process._stdout) : process._stdout,
      stderrEncoding == null ? utf8.encode(process._stderr) : process._stderr,
    );
  }

  /// Returns false if executable in [excludedExecutables].
  @override
  bool canRun(dynamic executable, {String workingDirectory}) => !excludedExecutables.contains(executable);

  Set<String> excludedExecutables = <String>{};

  @override
  bool killPid(int pid, [io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
    // Killing a fake process has no effect unless it has an attached completer.
    final _FakeProcess fakeProcess = _fakeRunningProcesses[pid];
    if (fakeProcess == null) {
      return false;
    }
    fakeProcess._completer.complete();
    return true;
  }
}

class _FakeAnyProcessManager extends FakeProcessManager {
  _FakeAnyProcessManager() : super._();

  @override
  FakeCommand findCommand(
    List<String> command,
    String workingDirectory,
    Map<String, String> environment,
    Encoding encoding,
  ) {
    return FakeCommand(
      command: command,
      workingDirectory: workingDirectory,
      environment: environment,
      encoding: encoding,
      duration: Duration.zero,
      exitCode: 0,
      stdout: '',
      stderr: '',
    );
  }

  @override
  void addCommand(FakeCommand command) { }

  @override
  bool get hasRemainingExpectations => true;

  @override
  List<FakeCommand> get _remainingExpectations => <FakeCommand>[];
}

class _SequenceProcessManager extends FakeProcessManager {
  _SequenceProcessManager(this._commands) : super._();

  final List<FakeCommand> _commands;

  @override
  FakeCommand findCommand(
    List<String> command,
    String workingDirectory,
    Map<String, String> environment,
    Encoding encoding,
  ) {
    expect(_commands, isNotEmpty,
      reason: 'ProcessManager was told to execute $command (in $workingDirectory) '
              'but the FakeProcessManager.list expected no more processes.'
    );
    _commands.first._matches(command, workingDirectory, environment, encoding);
    return _commands.removeAt(0);
  }

  @override
  void addCommand(FakeCommand command) {
    _commands.add(command);
  }

  @override
  bool get hasRemainingExpectations => _commands.isNotEmpty;

  @override
  List<FakeCommand> get _remainingExpectations => _commands;
}

/// Matcher that successfully matches against a [FakeProcessManager] with
/// no remaining expectations ([item.hasRemainingExpectations] returns false).
const Matcher hasNoRemainingExpectations = _HasNoRemainingExpectations();

class _HasNoRemainingExpectations extends Matcher {
  const _HasNoRemainingExpectations();

  @override
  bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
      item is FakeProcessManager && !item.hasRemainingExpectations;

  @override
  Description describe(Description description) =>
      description.add('a fake process manager with no remaining expectations');

  @override
  Description describeMismatch(
      dynamic item,
      Description description,
      Map<dynamic, dynamic> matchState,
      bool verbose,
      ) {
    final FakeProcessManager fakeProcessManager = item as FakeProcessManager;
    return description.add(
        'has remaining expectations:\n${fakeProcessManager._remainingExpectations.map((FakeCommand command) => command.command).join('\n')}');
  }
}
