use std::{
    io,
    os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd},
};

use runtime::rt::{
    process::{ProcessId, ProcessWait, WaitFlags},
    sys as syscall,
};

use crate::sys::PidFd;

pub struct PidFdImpl {
    fd: OwnedFd,
}

impl PidFd for PidFdImpl {
    fn new(pid: u32) -> io::Result<Self> {
        let pid = unsafe { ProcessId::from_raw(pid) };
        let target = ProcessWait::Process(pid);
        let fd = unsafe { syscall::create_pid(&target, WaitFlags::NON_BLOCKING) }
            .map_err(io::Error::from)?;
        let fd = unsafe { OwnedFd::from_raw_fd(fd) };
        Ok(Self { fd })
    }

    fn exit_status(&self) -> io::Result<i32> {
        let (_, code) = runtime::rt::io::read_pid_fd(self.fd.as_raw_fd())?;
        Ok(code)
    }
}

impl AsRawFd for PidFdImpl {
    fn as_raw_fd(&self) -> RawFd {
        self.fd.as_raw_fd()
    }
}
