use crate::io;
use crate::iter::Iterator;
use crate::mem::MaybeUninit;
use crate::os::uefi;
use crate::ptr::NonNull;

pub struct Stdin {
    surrogate: Option<u16>,
    incomplete_utf8: IncompleteUtf8,
}

struct IncompleteUtf8 {
    bytes: [u8; 4],
    len: u8,
}

impl IncompleteUtf8 {
    pub const fn new() -> IncompleteUtf8 {
        IncompleteUtf8 { bytes: [0; 4], len: 0 }
    }

    // Implemented for use in Stdin::read.
    fn read(&mut self, buf: &mut [u8]) -> usize {
        // Write to buffer until the buffer is full or we run out of bytes.
        let to_write = crate::cmp::min(buf.len(), self.len as usize);
        buf[..to_write].copy_from_slice(&self.bytes[..to_write]);

        // Rotate the remaining bytes if not enough remaining space in buffer.
        if usize::from(self.len) > buf.len() {
            self.bytes.copy_within(to_write.., 0);
            self.len -= to_write as u8;
        } else {
            self.len = 0;
        }

        to_write
    }
}

pub struct Stdout;
pub struct Stderr;

impl Stdin {
    pub const fn new() -> Stdin {
        Stdin { surrogate: None, incomplete_utf8: IncompleteUtf8::new() }
    }
}

impl io::Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // If there are bytes in the incomplete utf-8, start with those.
        // (No-op if there is nothing in the buffer.)
        let mut bytes_copied = self.incomplete_utf8.read(buf);

        let stdin: *mut r_efi::protocols::simple_text_input::Protocol = unsafe {
            let st: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
            (*st.as_ptr()).con_in
        };

        if bytes_copied == buf.len() {
            return Ok(bytes_copied);
        }

        let ch = simple_text_input_read(stdin)?;
        // Only 1 character should be returned.
        let mut ch: Vec<Result<char, crate::char::DecodeUtf16Error>> =
            if let Some(x) = self.surrogate.take() {
                char::decode_utf16([x, ch]).collect()
            } else {
                char::decode_utf16([ch]).collect()
            };

        if ch.len() > 1 {
            return Err(io::const_error!(io::ErrorKind::InvalidData, "invalid UTF-16 sequence"));
        }

        match ch.pop().unwrap() {
            Err(e) => {
                self.surrogate = Some(e.unpaired_surrogate());
            }
            Ok(x) => {
                // This will always be > 0
                let buf_free_count = buf.len() - bytes_copied;
                assert!(buf_free_count > 0);

                if buf_free_count >= x.len_utf8() {
                    // There is enough space in the buffer for the character.
                    bytes_copied += x.encode_utf8(&mut buf[bytes_copied..]).len();
                } else {
                    // There is not enough space in the buffer for the character.
                    // Store the character in the incomplete buffer.
                    self.incomplete_utf8.len =
                        x.encode_utf8(&mut self.incomplete_utf8.bytes).len() as u8;
                    // write partial character to buffer.
                    bytes_copied += self.incomplete_utf8.read(buf);
                }
            }
        }

        Ok(bytes_copied)
    }
}

impl Stdout {
    pub const fn new() -> Stdout {
        Stdout
    }
}

impl io::Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let st: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
        let stdout = unsafe { (*st.as_ptr()).con_out };

        write(stdout, buf)
    }

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

impl Stderr {
    pub const fn new() -> Stderr {
        Stderr
    }
}

impl io::Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let st: NonNull<r_efi::efi::SystemTable> = uefi::env::system_table().cast();
        let stderr = unsafe { (*st.as_ptr()).std_err };

        write(stderr, buf)
    }

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

// UTF-16 character should occupy 4 bytes at most in UTF-8
pub const STDIN_BUF_SIZE: usize = 4;

pub fn is_ebadf(err: &io::Error) -> bool {
    if let Some(x) = err.raw_os_error() {
        r_efi::efi::Status::UNSUPPORTED.as_usize() == x
    } else {
        false
    }
}

pub fn panic_output() -> Option<impl io::Write> {
    uefi::env::try_system_table().map(|_| Stderr::new())
}

fn write(
    protocol: *mut r_efi::protocols::simple_text_output::Protocol,
    buf: &[u8],
) -> io::Result<usize> {
    // Get valid UTF-8 buffer
    let utf8 = match crate::str::from_utf8(buf) {
        Ok(x) => x,
        Err(e) => unsafe { crate::str::from_utf8_unchecked(&buf[..e.valid_up_to()]) },
    };

    let mut utf16: Vec<u16> = utf8.encode_utf16().collect();
    // NULL terminate the string
    utf16.push(0);

    unsafe { simple_text_output(protocol, &mut utf16) }?;

    Ok(utf8.len())
}

unsafe fn simple_text_output(
    protocol: *mut r_efi::protocols::simple_text_output::Protocol,
    buf: &mut [u16],
) -> io::Result<()> {
    let res = unsafe { ((*protocol).output_string)(protocol, buf.as_mut_ptr()) };
    if res.is_error() { Err(io::Error::from_raw_os_error(res.as_usize())) } else { Ok(()) }
}

fn simple_text_input_read(
    stdin: *mut r_efi::protocols::simple_text_input::Protocol,
) -> io::Result<u16> {
    loop {
        match read_key_stroke(stdin) {
            Ok(x) => return Ok(x.unicode_char),
            Err(e) if e == r_efi::efi::Status::NOT_READY => wait_stdin(stdin)?,
            Err(e) => return Err(io::Error::from_raw_os_error(e.as_usize())),
        }
    }
}

fn wait_stdin(stdin: *mut r_efi::protocols::simple_text_input::Protocol) -> io::Result<()> {
    let boot_services: NonNull<r_efi::efi::BootServices> =
        uefi::env::boot_services().unwrap().cast();
    let wait_for_event = unsafe { (*boot_services.as_ptr()).wait_for_event };
    let wait_for_key_event = unsafe { (*stdin).wait_for_key };

    let r = {
        let mut x: usize = 0;
        (wait_for_event)(1, [wait_for_key_event].as_mut_ptr(), &mut x)
    };
    if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}

fn read_key_stroke(
    stdin: *mut r_efi::protocols::simple_text_input::Protocol,
) -> Result<r_efi::protocols::simple_text_input::InputKey, r_efi::efi::Status> {
    let mut input_key: MaybeUninit<r_efi::protocols::simple_text_input::InputKey> =
        MaybeUninit::uninit();

    let r = unsafe { ((*stdin).read_key_stroke)(stdin, input_key.as_mut_ptr()) };

    if r.is_error() {
        Err(r)
    } else {
        let input_key = unsafe { input_key.assume_init() };
        Ok(input_key)
    }
}
