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

use crate::sys::PidFd;

pub struct PidFdImpl {
    fd: OwnedFd,
    pid: i32,
}

impl PidFd for PidFdImpl {
    fn new(pid: u32) -> io::Result<Self> {
        let pid = pid as i32;
        let fd = unsafe { libc::syscall(libc::SYS_pidfd_open, pid, libc::PIDFD_NONBLOCK) } as i32;
        if fd < 0 {
            return Err(io::Error::last_os_error());
        }
        let fd = unsafe { OwnedFd::from_raw_fd(fd) };
        Ok(Self { fd, pid })
    }

    fn exit_status(&self) -> io::Result<i32> {
        let mut status = 0;
        let res = unsafe { libc::waitpid(self.pid, &mut status, 0) };
        if res < 0 {
            return Err(io::Error::last_os_error());
        }
        Ok(status)
    }
}

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