// 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.

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,
    this.outputFollowsExit = false,
  }) : 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 Object? exception;

  /// Indicates that output will only be emitted after the `exitCode` [Future]
  /// on [io.Process] completes.
  final bool outputFollowsExit;

  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,
    IOSink? stdin,
    this._stdout,
    this._completer,
    bool outputFollowsExit,
  ) : exitCode = Future<void>.delayed(duration).then((void value) {
        if (_completer != null) {
          return _completer.future.then((void _) => _exitCode);
        }
        return _exitCode;
      }),
      stdin = stdin ?? IOSink(StreamController<List<int>>().sink)
  {
    if (_stderr == null) {
      stderr = const Stream<List<int>>.empty();
    } else if (outputFollowsExit) {
      stderr = Stream<List<int>>.fromFuture(exitCode.then((_) {
        return Future<List<int>>(() => utf8.encode(_stderr));
      }));
    } else {
      stderr = Stream<List<int>>.value(utf8.encode(_stderr));
    }

    if (_stdout == null) {
      stdout = const Stream<List<int>>.empty();
    } else if (outputFollowsExit) {
      stdout = Stream<List<int>>.fromFuture(exitCode.then((_) {
        return Future<List<int>>(() => utf8.encode(_stdout));
      }));
    } else {
      stdout = 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
  late final Stream<List<int>> stderr;

  @override
  final IOSink stdin;

  @override
  late 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;
  factory FakeProcessManager.empty() => _SequenceProcessManager(<FakeCommand>[]);

  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,
      fakeCommand.outputFollowsExit,
    );
  }

  @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;
    }
    if (fakeProcess._completer != null) {
      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,
    );
  }

  @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')}');
  }
}
