use std::{
    fs::File,
    io::{self, Read, Write},
    os::{
        fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd},
        yggdrasil::io::pipe::create_pipe_pair,
    },
    process::Stdio,
};

use crate::sys::Pipe;

pub struct PipeImpl {
    file: File,
}

impl Pipe for PipeImpl {
    fn new(read_nonblocking: bool, write_nonblocking: bool) -> io::Result<(Self, Self)> {
        let (read, write) = create_pipe_pair(read_nonblocking, write_nonblocking)?;
        let read = unsafe { File::from_raw_fd(read.into_raw_fd()) };
        let write = unsafe { File::from_raw_fd(write.into_raw_fd()) };
        Ok((Self { file: read }, Self { file: write }))
    }

    fn to_child_stdio(&self) -> Stdio {
        unsafe { Stdio::from_raw_fd(self.as_raw_fd()) }
    }
}

impl Write for PipeImpl {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.file.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.file.flush()
    }
}

impl Read for PipeImpl {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.file.read(buf)
    }
}

impl AsRawFd for PipeImpl {
    fn as_raw_fd(&self) -> RawFd {
        self.file.as_raw_fd()
    }
}
