#![unstable(feature = "yggdrasil_os", issue = "none")]

use crate::io;
use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
use crate::sys::cvt_io;
use crate::time::Duration;

use yggdrasil_rt::io::poll as rt;

#[unstable(feature = "yggdrasil_os", issue = "none")]
pub type PollControl = rt::PollControl;

#[unstable(feature = "yggdrasil_os", issue = "none")]
pub struct PollChannel(OwnedFd);

impl PollChannel {
    #[unstable(feature = "yggdrasil_os", issue = "none")]
    pub fn new() -> io::Result<Self> {
        let raw_fd = cvt_io(unsafe { yggdrasil_rt::sys::create_poll_channel() })?;
        let fd = unsafe { OwnedFd::from_raw_fd(raw_fd) };
        Ok(Self(fd))
    }

    #[unstable(feature = "yggdrasil_os", issue = "none")]
    pub fn add(&mut self, fd: RawFd) -> io::Result<()> {
        cvt_io(unsafe {
            yggdrasil_rt::sys::poll_channel_control(self.0.as_raw_fd(), PollControl::AddFd, fd)
        })
    }

    #[unstable(feature = "yggdrasil_os", issue = "none")]
    pub fn wait(
        &mut self,
        timeout: Option<Duration>,
    ) -> io::Result<Option<(RawFd, io::Result<()>)>> {
        let mut output = None;
        cvt_io(unsafe {
            yggdrasil_rt::sys::poll_channel_wait(self.0.as_raw_fd(), &timeout, &mut output)
        })?;
        Ok(output.map(|(l, r)| (l, cvt_io(r))))
    }
}

#[unstable(feature = "yggdrasil_os", issue = "none")]
impl AsRawFd for PollChannel {
    fn as_raw_fd(&self) -> RawFd {
        self.0.as_raw_fd()
    }
}
