# :nodoc:
struct Crystal::System::Process
  # Implementation-dependent "conceptual" data types (they only need to match across arg types and return types):
  # * ProcessInformation: The system-dependent value with enough information to keep track of a running process.
  #   Could be the PID or similar.
  # * Args: The system-native way to specify an executable with its command line arguments.
  #   Could be an array of strings or a single string.

  # Creates a structure representing a running process based on its ID.
  # def self.new(pi : ProcessInformation)

  # Releases any resources acquired by this structure.
  # def release

  # Returns the PID of the running process.
  # def pid : Int

  # Waits until the process finishes and returns its status code
  # def wait : Int

  # Whether the process is still registered in the system.
  # def exists? : Bool

  # Asks this process to terminate.
  # def terminate(*, graceful)

  # Terminates the current process immediately.
  # def self.exit(status : Int)

  # Returns the process identifier of the current process.
  # def self.pid : Int

  # Returns the process group identifier of the current process.
  # def self.pgid : Int

  # Returns the process group identifier of the process identified by *pid*.
  # def self.pgid(pid) : Int

  # Returns the process identifier of the parent process of the current process.
  # def self.ppid : Int

  # Sends a *signal* to the processes identified by the given *pids*.
  # def self.signal(pid : Int, signal : Int)

  # Installs *handler* as the new handler for interrupt requests. Removes any
  # previously set interrupt handler.
  # def self.on_interrupt(&handler : ->)

  # Installs *handler* as the new handler for termination signals. Removes any
  # previously set handler.
  # def self.on_terminate(&handler : ::Process::ExitReason ->)

  # Ignores all interrupt requests. Removes any custom interrupt handler set
  # def self.ignore_interrupts!

  # Restores default handling of interrupt requests.
  # def self.restore_interrupts!

  # Returns whether a debugger is attached to the current process.
  # def self.debugger_present? : Bool

  # Spawns a fiber responsible for executing interrupt handlers on the main
  # thread.
  # def self.start_interrupt_loop

  # Whether the process identified by *pid* is still registered in the system.
  # def self.exists?(pid : Int) : Bool

  # Measures CPU times.
  # def self.times : ::Process::Tms

  # Duplicates the current process.
  # def self.fork : ProcessInformation
  # def self.fork(&)

  # def prepare_args(command : String, args : Enumerable(String)?, shell : Bool) : Args
  # def prepare_args(args : Enumerable(String)) : Args

  # Launches a child process with the command + args.
  # def self.spawn(prepared_args : Args, shell : Bool, env : Env?, clear_env : Bool, input : Stdio, output : Stdio, error : Stdio, chdir : Path | String?) : ProcessInformation

  # Replaces the current process with a new one.
  # def self.replace(command : String, args : Enumerable(String)?, shell : Bool, env : Env?, clear_env : Bool, input : Stdio, output : Stdio, error : Stdio, chdir : Path | String?) : NoReturn

  # Changes the root directory for the current process.
  # def self.chroot(path : String)
end

module Crystal::System
  ORIGINAL_STDIN  = IO::FileDescriptor.new(handle: Crystal::System::FileDescriptor::STDIN_HANDLE, blocking: true)
  ORIGINAL_STDOUT = IO::FileDescriptor.new(handle: Crystal::System::FileDescriptor::STDOUT_HANDLE, blocking: true)
  ORIGINAL_STDERR = IO::FileDescriptor.new(handle: Crystal::System::FileDescriptor::STDERR_HANDLE, blocking: true)
end

{% if flag?(:wasi) %}
  require "./wasi/process"
{% elsif flag?(:unix) %}
  require "./unix/process"
{% elsif flag?(:win32) %}
  require "./win32/process"
{% else %}
  {% raise "No Crystal::System::Process implementation available" %}
{% end %}
