// Copyright 2013 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:convert';
import 'dart:io' as io;

import 'package:process/process.dart';

/// A fake implementation of [ProcessManager] that allows control for testing.
final class FakeProcessManager implements ProcessManager {
  /// Creates a fake process manager delegates to [onRun] and [onStart].
  ///
  /// If either is not provided, it throws an [UnsupportedError] when called.
  FakeProcessManager({
    io.ProcessResult Function(List<String> command) onRun = unhandledRun,
    io.Process Function(List<String> command) onStart = unhandledStart,
    bool Function(Object?, {String? workingDirectory}) canRun = unhandledCanRun,
  }) : _onRun = onRun, _onStart = onStart, _canRun = canRun;

  /// A default implementation of [onRun] that throws an [UnsupportedError].
  static io.ProcessResult unhandledRun(List<String> command) {
    throw UnsupportedError('Unhandled run: ${command.join(' ')}');
  }

  /// A default implementation of [onStart] that throws an [UnsupportedError].
  static io.Process unhandledStart(List<String> command) {
    throw UnsupportedError('Unhandled start: ${command.join(' ')}');
  }

  /// A default implementation of [canRun] that returns `true`.
  static bool unhandledCanRun(Object? executable, {String? workingDirectory}) {
    return true;
  }

  final io.ProcessResult Function(List<String> command) _onRun;
  final io.Process Function(List<String> command) _onStart;
  final bool Function(Object?, {String? workingDirectory}) _canRun;

  @override
  bool canRun(Object? executable, {String? workingDirectory}) {
    return _canRun(executable, workingDirectory: workingDirectory);
  }

  @override
  bool killPid(int pid, [io.ProcessSignal signal = io.ProcessSignal.sigterm]) => true;

  @override
  Future<io.ProcessResult> run(
    List<Object> command, {
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment = true,
    bool runInShell = false,
    Encoding stdoutEncoding = io.systemEncoding,
    Encoding stderrEncoding = io.systemEncoding,
  }) async {
    return runSync(
      command,
      workingDirectory: workingDirectory,
      environment: environment,
      includeParentEnvironment: includeParentEnvironment,
      runInShell: runInShell,
      stdoutEncoding: stdoutEncoding,
      stderrEncoding: stderrEncoding,
    );
  }

  @override
  io.ProcessResult runSync(
    List<Object> command, {
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment = true,
    bool runInShell = false,
    Encoding stdoutEncoding = io.systemEncoding,
    Encoding stderrEncoding = io.systemEncoding,
  }) {
    return _onRun(command.map((Object o) => '$o').toList());
  }

  @override
  Future<io.Process> start(
    List<Object> command, {
    String? workingDirectory,
    Map<String, String>? environment,
    bool includeParentEnvironment = true,
    bool runInShell = false,
    io.ProcessStartMode mode = io.ProcessStartMode.normal,
  }) async {
    return _onStart(command.map((Object o) => '$o').toList());
  }
}

/// An incomplete fake of [io.Process] that allows control for testing.
final class FakeProcess implements io.Process {
  /// Creates a fake process that returns the given [exitCode] and out/err.
  FakeProcess({
    int exitCode = 0,
    String stdout = '',
    String stderr = '',
  })  : _exitCode = exitCode,
        _stdout = stdout,
        _stderr = stderr;

  final int _exitCode;
  final String _stdout;
  final String _stderr;

  @override
  Future<int> get exitCode async => _exitCode;

  @override
  bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) => true;

  @override
  int get pid => 0;

  @override
  Stream<List<int>> get stderr {
    return Stream<List<int>>.fromIterable(<List<int>>[io.systemEncoding.encoder.convert(_stderr)]);
  }

  @override
  io.IOSink get stdin => throw UnimplementedError();

  @override
  Stream<List<int>> get stdout {
    return Stream<List<int>>.fromIterable(<List<int>>[io.systemEncoding.encoder.convert(_stdout)]);
  }
}
