// ignore_for_file: depend_on_referenced_packages

import 'dart:convert';
import 'dart:io';

import 'package:dart_framework/platform/process.dart';

abstract class SystemRuntime {
  bool get isWindows;
  bool get isMacOS;
  bool get isLinux;
  Map<String, String> get environment;

  Future<ProcessData> startShell(
    StringBuffer shell, {
    String? workspace,
    bool printStdout = true,
    bool printStderr = true,
    Converter<List<int>, String>? decoder,
    LogHandler? logHandler,
  });

  Future<ProcessResult> runShell(
    StringBuffer shell, {
    String? workspace,
    bool printStdout = true,
    bool printStderr = true,
    Converter<List<int>, String>? decoder,
    LogHandler? logHandler,
  });

  Future<ProcessResult> runExecutable(
    String exe,
    List<String> args, {
    String? workingDirectory,
    Encoding? stdoutEncoding,
    Encoding? stderrEncoding,
  });

  Future<Process> startExecutable(
    String program,
    List<String> args, {
    String? workingDirectory,
    ProcessStartMode mode = ProcessStartMode.normal,
  });

  bool killPid(int pid, [ProcessSignal signal = ProcessSignal.sigterm]);
}

class DefaultSystemRuntime implements SystemRuntime {
  const DefaultSystemRuntime();

  @override
  bool get isWindows => Platform.isWindows;

  @override
  bool get isMacOS => Platform.isMacOS;

  @override
  bool get isLinux => Platform.isLinux;

  @override
  Map<String, String> get environment => Platform.environment;

  @override
  Future<ProcessData> startShell(
    StringBuffer shell, {
    String? workspace,
    bool printStdout = true,
    bool printStderr = true,
    Converter<List<int>, String>? decoder,
    LogHandler? logHandler,
  }) {
    return ProcessExecutor.start(
      shell,
      workspace: workspace,
      printStdout: printStdout,
      printStderr: printStderr,
      decoder: decoder,
      logHandler: logHandler,
    );
  }

  @override
  Future<ProcessResult> runShell(
    StringBuffer shell, {
    String? workspace,
    bool printStdout = true,
    bool printStderr = true,
    Converter<List<int>, String>? decoder,
    LogHandler? logHandler,
  }) {
    return ProcessExecutor.run(
      shell,
      workspace: workspace,
      printStdout: printStdout,
      printStderr: printStderr,
      decoder: decoder,
      logHandler: logHandler,
    );
  }

  @override
  Future<ProcessResult> runExecutable(
    String exe,
    List<String> args, {
    String? workingDirectory,
    Encoding? stdoutEncoding,
    Encoding? stderrEncoding,
  }) {
    return Process.run(
      exe,
      args,
      workingDirectory: workingDirectory,
      stdoutEncoding: stdoutEncoding,
      stderrEncoding: stderrEncoding,
    );
  }

  @override
  Future<Process> startExecutable(
    String program,
    List<String> args, {
    String? workingDirectory,
    ProcessStartMode mode = ProcessStartMode.normal,
  }) {
    return Process.start(
      program,
      args,
      workingDirectory: workingDirectory,
      mode: mode,
    );
  }

  @override
  bool killPid(int pid, [ProcessSignal signal = ProcessSignal.sigterm]) {
    return Process.killPid(pid, signal);
  }
}
