//! Types related to getting and setting an input element's value.

use crate::dom::element::DomElement;

/// An error when attempting to retrieve an input element's value.
#[derive(Debug)]
pub enum InputElementGetValueError {
    /// The element was not an `<input>` element.
    ElementIsNotHtmlInputElement,
    /// The out buffer was smaller than the minimum allowed size.
    OutBufferBelowMinimumSize,
    /// The out buffer was smaller than the length of the input element's value.
    #[allow(missing_docs)]
    OutBufferSmallerThanValue { value_len: usize },
    #[allow(missing_docs)]
    Unrecognized { error_code: i32 },
}

impl DomElement {
    /// Get the input element's value.
    pub fn value<'out>(
        &self,
        out_buffer: &'out mut [u8],
    ) -> Result<&'out str, InputElementGetValueError> {
        let returned = unsafe {
            afia_component_sys::input_element_value(
                self.component_imports_ptr(),
                self.to_i64(),
                out_buffer.as_mut_ptr(),
                out_buffer.len(),
            )
        };

        match returned {
            length if length >= 0 => {
                let length = length as usize;

                // SAFETY: here we are trusting that the Afia host worked as expected and wrote a
                // utf8 string to the buffer.
                let string = unsafe { std::str::from_utf8_unchecked(&out_buffer[0..length]) };

                Ok(string)
            }
            -3 => Err(InputElementGetValueError::ElementIsNotHtmlInputElement),
            -4 => Err(InputElementGetValueError::OutBufferBelowMinimumSize),
            -5 => {
                let mut val_len = [0; 4];
                val_len.copy_from_slice(&out_buffer[0..4]);
                let val = i32::from_le_bytes(val_len);
                Err(InputElementGetValueError::OutBufferSmallerThanValue {
                    value_len: val as usize,
                })
            }
            unknown_error_code => Err(InputElementGetValueError::Unrecognized {
                error_code: unknown_error_code,
            }),
        }
    }
}
