// TODO: refactor this file
// TODO: make STDOUT redirect to a socket owned
//       by the process named "stdout"

use core::fmt::{Arguments, Error};

pub struct Stdout;
impl Stdout {
    pub fn write_fmt(&mut self, arg: Arguments<'_>) /*-> Result<(), Error> */
    {
        let _ = core::fmt::Write::write_fmt(self, arg);
        //   Ok(())
    }
}

impl core::fmt::Write for Stdout {
    #[cfg(target_arch = "aarch64")]
    fn write_str(&mut self, s: &str) -> Result<(), Error> {
        // Don't actually print anything yet lmao
        Ok(())
    }
    #[cfg(target_arch = "x86_64")]
    fn write_str(&mut self, s: &str) -> Result<(), Error> {
        // use mini_backtrace::Backtrace;

        use crate::TERM;

        // Capture up to 16 frames. This is returned using an ArrayVec that doesn't
        // perform any dynamic memory allocation.
        /*
        let bt = Backtrace::<16>::capture();
        trace!("Backtrace:");
        for frame in bt.frames {
            trace!("  {:#x}", frame);
        }
        if bt.frames_omitted {
            trace!(" ... <frames omitted>");
        }
        */

        // trace!("printing");
        // x86_64::instructions::interrupts::without_interrupts(|| {
        let mut term = TERM.lock();

        term.set_dirty(true);
        term.print(s);

        drop(term);
        // });
        // trace!("Finished printing");
        Ok(())
    }
    #[cfg(target_arch = "riscv64")]
    fn write_str(&mut self, s: &str) -> Result<(), Error> {
        Ok(())
    }
    fn write_char(&mut self, c: char) -> core::fmt::Result {
        self.write_str(c.encode_utf8(&mut [0; 4]))
    }
    fn write_fmt(mut self: &mut Self, args: Arguments<'_>) -> core::fmt::Result {
        core::fmt::write(&mut self, args)
    }
}

#[macro_export]
macro_rules! print {
    () => {
        ::core::writeln!($crate::print::Stdout, "")
    };
    ($($tt:tt)*) => {
        ::core::write!($crate::print::Stdout, $($tt)*)
    };
}
#[macro_export]
macro_rules! println {
    ($($tt:tt)*) => {
        ::core::writeln!($crate::print::Stdout, $($tt)*)
    };
}
