//! Native LLSD/OSD value model.
//!
//! The model is deliberately independent of every wire-format implementation.
//! Maps have no observable ordering contract; serializers that require stable
//! output must impose their own ordering. Collection access returns owned
//! snapshots, matching the value-oriented Rust boundary while preventing locks
//! or borrows from escaping a call.

#![allow(clippy::cast_possible_truncation)]
#![allow(clippy::cast_possible_wrap)] // C# unchecked numeric conversions are reference behavior.
#![allow(clippy::cast_precision_loss)] // C# converts integral bounds through Double for these APIs.
#![allow(clippy::cast_sign_loss)]
#![allow(clippy::format_collect)] // Hex conversion is small and mirrors the reference allocation.
#![allow(clippy::inherent_to_string)]
#![allow(clippy::match_same_arms)] // Unsupported mapped object variants intentionally become undefined.
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_panics_doc)] // Infallible mapped operators and indexers have fixed signatures.
#![allow(clippy::must_use_candidate)]
#![allow(clippy::needless_pass_by_value)]
#![allow(clippy::should_implement_trait)]

use base64::Engine as _;
use libremetaverse_types::compat::{
    ArrayList, ExternalError, Hashtable, IDictionaryEnumerator, Object, TypeId, Uri,
};
use libremetaverse_types::{Color4, Error, Quaternion, UUID, Vector2, Vector3, Vector3d, Vector4};
use std::collections::HashMap;
use std::fmt::Write as _;
use std::hash::{Hash, Hasher};
use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::time::{Duration, SystemTime, UNIX_EPOCH};

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(u8)]
pub enum OSDType {
    Unknown = 0,
    Boolean = 1,
    Integer = 2,
    Real = 3,
    String = 4,
    UUID = 5,
    Date = 6,
    URI = 7,
    Binary = 8,
    Map = 9,
    Array = 10,
    LlsdXml = 11,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[repr(i32)]
pub enum OSDFormat {
    Xml = 0,
    Json = 1,
    Binary = 2,
}

/// A format-neutral LLSD value.
///
/// Equality and hashing are structural. Real values compare by their IEEE-754
/// bit pattern so that hashing remains valid for NaNs and signed zero. Map
/// hashing sorts keys first, because [`HashMap`] iteration order is unspecified.
///
/// Typed accessors follow `LibreMetaverse`'s permissive conversion contract:
/// unsupported conversions return the type's default (`false`, zero, an empty
/// string or byte vector, the nil UUID, the Unix epoch, or no URI). Integer and
/// real conversions retain the reference's unchecked wrapping, clamping, and
/// round-to-even behavior. Binary integers use network byte order; date binary
/// values use the reference's little-endian floating-point Unix timestamp.
/// Owned variants make cloning structural and keep all borrowing local to the
/// call, so no parser or serializer implementation controls this representation.
#[non_exhaustive]
#[derive(Clone, Debug, Default)]
pub enum OSD {
    #[default]
    Undefined,
    Boolean(bool),
    Integer(i32),
    Real(f64),
    String(String),
    UUID(UUID),
    Date(SystemTime),
    Uri(Uri),
    Binary(Vec<u8>),
    Array(Vec<OSD>),
    Map(HashMap<String, OSD>),
    LlsdXml(String),
}

impl PartialEq for OSD {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Undefined, Self::Undefined) => true,
            (Self::Boolean(left), Self::Boolean(right)) => left == right,
            (Self::Integer(left), Self::Integer(right)) => left == right,
            (Self::Real(left), Self::Real(right)) => left.to_bits() == right.to_bits(),
            (Self::String(left), Self::String(right))
            | (Self::LlsdXml(left), Self::LlsdXml(right)) => left == right,
            (Self::UUID(left), Self::UUID(right)) => left == right,
            (Self::Date(left), Self::Date(right)) => left == right,
            (Self::Uri(left), Self::Uri(right)) => left == right,
            (Self::Binary(left), Self::Binary(right)) => left == right,
            (Self::Array(left), Self::Array(right)) => left == right,
            (Self::Map(left), Self::Map(right)) => left == right,
            _ => false,
        }
    }
}

impl Eq for OSD {}

impl Hash for OSD {
    fn hash<H: Hasher>(&self, state: &mut H) {
        std::mem::discriminant(self).hash(state);
        match self {
            Self::Undefined => {}
            Self::Boolean(value) => value.hash(state),
            Self::Integer(value) => value.hash(state),
            Self::Real(value) => value.to_bits().hash(state),
            Self::String(value) | Self::LlsdXml(value) => value.hash(state),
            Self::UUID(value) => value.hash(state),
            Self::Date(value) => value.hash(state),
            Self::Uri(value) => value.hash(state),
            Self::Binary(value) => value.hash(state),
            Self::Array(value) => value.hash(state),
            Self::Map(value) => {
                let mut entries: Vec<_> = value.iter().collect();
                entries.sort_unstable_by_key(|(key, _)| *key);
                entries.hash(state);
            }
        }
    }
}

impl OSD {
    pub const DEFAULT_MAX_DEPTH: usize = 64;
    pub const DEFAULT_MAX_NODES: usize = 1_000_000;
    pub const DEFAULT_MAX_BINARY_BYTES: usize = 64 * 1024 * 1024;

    pub const fn new() -> Result<Self, Error> {
        Ok(Self::Undefined)
    }

    /// Checks recursively allocated data before accepting a value from an
    /// untrusted parser boundary. Format parsers call this after decoding.
    pub fn validate_limits(
        &self,
        max_depth: usize,
        max_nodes: usize,
        max_binary_bytes: usize,
    ) -> Result<(), Error> {
        let mut nodes = 0_usize;
        let mut binary_bytes = 0_usize;
        let mut stack = vec![(self, 0_usize)];
        while let Some((value, depth)) = stack.pop() {
            if depth > max_depth {
                return Err(Error::Argument);
            }
            nodes = nodes.checked_add(1).ok_or(Error::Argument)?;
            if nodes > max_nodes {
                return Err(Error::Argument);
            }
            match value {
                Self::Binary(bytes) => {
                    binary_bytes = binary_bytes
                        .checked_add(bytes.len())
                        .ok_or(Error::Argument)?;
                    if binary_bytes > max_binary_bytes {
                        return Err(Error::Argument);
                    }
                }
                Self::Array(values) => {
                    stack.extend(values.iter().map(|value| (value, depth + 1)));
                }
                Self::Map(values) => {
                    stack.extend(values.values().map(|value| (value, depth + 1)));
                }
                _ => {}
            }
        }
        Ok(())
    }

    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(match self {
            Self::Boolean(value) => vec![if *value { b'1' } else { b'0' }],
            Self::Integer(value) => value.to_be_bytes().to_vec(),
            Self::Real(value) => value.to_be_bytes().to_vec(),
            Self::String(value) | Self::LlsdXml(value) => value.as_bytes().to_vec(),
            Self::UUID(value) => value.get_bytes()?,
            Self::Date(value) => unix_seconds_for_codec(*value).to_le_bytes().to_vec(),
            Self::Uri(value) => value.0.as_bytes().to_vec(),
            Self::Binary(value) => value.clone(),
            Self::Array(values) => values
                .iter()
                .map(|value| value.as_integer().map(|integer| integer as u8))
                .collect::<Result<Vec<_>, _>>()?,
            _ => Vec::new(),
        })
    }

    pub fn as_boolean(&self) -> Result<bool, Error> {
        Ok(match self {
            Self::Boolean(value) => *value,
            Self::Integer(value) => *value != 0,
            Self::Real(value) => !value.is_nan() && *value != 0.0,
            Self::String(value) => string_as_boolean(value),
            Self::UUID(value) => *value != UUID::zero(),
            Self::Array(value) => !value.is_empty(),
            Self::Map(value) => !value.is_empty(),
            _ => false,
        })
    }

    pub fn as_integer(&self) -> Result<i32, Error> {
        Ok(match self {
            Self::Boolean(value) => i32::from(*value),
            Self::Integer(value) => *value,
            Self::Real(value) => real_to_i32(*value),
            Self::String(value) => string_to_f64(value).map_or(0, floor_to_i32),
            Self::Date(value) => unix_seconds_u32(*value) as i32,
            _ => 0,
        })
    }

    pub fn as_u_integer(&self) -> Result<u32, Error> {
        Ok(match self {
            Self::Integer(value) => *value as u32,
            Self::Real(value) => real_to_u32(*value),
            Self::String(value) => string_to_f64(value).map_or(0, floor_to_u32),
            Self::Date(value) => unix_seconds_u32(*value),
            Self::Binary(value) => read_u32(value)?,
            Self::Array(value) => read_u32(&Self::Array(value.clone()).as_binary()?)?,
            _ => self.as_integer()? as u32,
        })
    }

    pub fn as_long(&self) -> Result<i64, Error> {
        Ok(match self {
            Self::Integer(value) => i64::from(*value),
            Self::Real(value) => real_to_i64(*value),
            Self::String(value) => string_to_f64(value).map_or(0, floor_to_i64),
            Self::Date(value) => i64::from(unix_seconds_u32(*value)),
            Self::Binary(value) => read_i64(value)?,
            Self::Array(value) => read_i64(&Self::Array(value.clone()).as_binary()?)?,
            _ => 0,
        })
    }

    pub fn as_u_long(&self) -> Result<u64, Error> {
        Ok(match self {
            Self::Integer(value) => *value as u64,
            Self::Real(value) => real_to_u64(*value),
            Self::String(value) => string_to_f64(value).map_or(0, floor_to_u64),
            Self::Date(value) => u64::from(unix_seconds_u32(*value)),
            Self::Binary(value) => read_u64(value)?,
            Self::Array(value) => read_u64(&Self::Array(value.clone()).as_binary()?)?,
            _ => 0,
        })
    }

    pub fn as_real(&self) -> Result<f64, Error> {
        Ok(match self {
            Self::Boolean(value) => f64::from(u8::from(*value)),
            Self::Integer(value) => f64::from(*value),
            Self::Real(value) => *value,
            Self::String(value) => string_to_f64(value).unwrap_or(0.0),
            _ => 0.0,
        })
    }

    pub fn as_string(&self) -> Result<String, Error> {
        Ok(match self {
            Self::Boolean(value) => if *value { "1" } else { "0" }.to_owned(),
            Self::Integer(value) => value.to_string(),
            Self::Real(value) => format_real_for_codec(*value),
            Self::String(value) | Self::LlsdXml(value) => value.clone(),
            Self::UUID(value) => value.to_string(),
            Self::Date(value) => format_system_time_for_codec(*value),
            Self::Uri(value) => format_uri_for_codec(&value.0),
            Self::Binary(value) => base64::engine::general_purpose::STANDARD.encode(value),
            _ => String::new(),
        })
    }

    pub fn as_uuid(&self) -> Result<UUID, Error> {
        match self {
            Self::UUID(value) => Ok(*value),
            Self::String(value) => {
                Ok(UUID::new_with_string(value.clone()).unwrap_or_else(|_| UUID::zero()))
            }
            _ => Ok(UUID::zero()),
        }
    }

    pub fn as_date(&self) -> Result<SystemTime, Error> {
        Ok(match self {
            Self::Date(value) => *value,
            Self::String(value) => parse_system_time_for_codec(value).unwrap_or(UNIX_EPOCH),
            _ => UNIX_EPOCH,
        })
    }

    pub fn as_uri(&self) -> Result<Option<Uri>, Error> {
        Ok(match self {
            Self::Uri(value) => Some(value.clone()),
            Self::String(value) if valid_uri_reference(value) => Some(Uri(value.clone())),
            _ => None,
        })
    }

    pub fn as_vector2(&self) -> Result<Vector2, Error> {
        match self {
            Self::Array(value) if value.len() == 2 => Vector2::new_with_single_single(
                value[0].as_real()? as f32,
                value[1].as_real()? as f32,
            ),
            _ => Ok(Vector2::zero()),
        }
    }

    pub fn as_vector3(&self) -> Result<Vector3, Error> {
        match self {
            Self::Array(value) if value.len() == 3 => Vector3::new_with_single_single_single(
                value[0].as_real()? as f32,
                value[1].as_real()? as f32,
                value[2].as_real()? as f32,
            ),
            _ => Ok(Vector3::zero()),
        }
    }

    pub fn as_vector3d(&self) -> Result<Vector3d, Error> {
        match self {
            Self::Array(value) if value.len() == 3 => Vector3d::new_with_double_double_double(
                value[0].as_real()?,
                value[1].as_real()?,
                value[2].as_real()?,
            ),
            _ => Ok(Vector3d::zero()),
        }
    }

    pub fn as_vector4(&self) -> Result<Vector4, Error> {
        match self {
            Self::Array(value) if value.len() == 4 => {
                Vector4::new_with_single_single_single_single(
                    value[0].as_real()? as f32,
                    value[1].as_real()? as f32,
                    value[2].as_real()? as f32,
                    value[3].as_real()? as f32,
                )
            }
            _ => Ok(Vector4::zero()),
        }
    }

    pub fn as_quaternion(&self) -> Result<Quaternion, Error> {
        match self {
            Self::Array(value) if value.len() == 4 => {
                Quaternion::new_with_single_single_single_single(
                    value[0].as_real()? as f32,
                    value[1].as_real()? as f32,
                    value[2].as_real()? as f32,
                    value[3].as_real()? as f32,
                )
            }
            _ => Ok(Quaternion::identity()),
        }
    }

    pub fn as_color4(&self) -> Result<Color4, Error> {
        match self {
            Self::Array(value) if value.len() == 4 => Color4::new_with_single_single_single_single(
                (value[0].as_real()? as f32).clamp(0.0, 1.0),
                (value[1].as_real()? as f32).clamp(0.0, 1.0),
                (value[2].as_real()? as f32).clamp(0.0, 1.0),
                (value[3].as_real()? as f32).clamp(0.0, 1.0),
            ),
            _ => Ok(Color4::black()),
        }
    }

    pub fn copy(&self) -> Result<Self, Error> {
        Ok(self.clone())
    }

    pub fn from_boolean(value: bool) -> Result<Self, Error> {
        Ok(Self::Boolean(value))
    }
    pub fn from_integer_with_int32(value: i32) -> Result<Self, Error> {
        Ok(Self::Integer(value))
    }
    pub fn from_integer_with_u_int32(value: u32) -> Result<Self, Error> {
        Ok(Self::Integer(value as i32))
    }
    pub fn from_integer_with_int16(value: i16) -> Result<Self, Error> {
        Ok(Self::Integer(i32::from(value)))
    }
    pub fn from_integer_with_u_int16(value: u16) -> Result<Self, Error> {
        Ok(Self::Integer(i32::from(value)))
    }
    pub fn from_integer_with_s_byte(value: i8) -> Result<Self, Error> {
        Ok(Self::Integer(i32::from(value)))
    }
    pub fn from_integer_with_byte(value: u8) -> Result<Self, Error> {
        Ok(Self::Integer(i32::from(value)))
    }
    pub fn from_u_integer(value: u32) -> Result<Self, Error> {
        Ok(Self::Binary(value.to_be_bytes().to_vec()))
    }
    pub fn from_long(value: i64) -> Result<Self, Error> {
        Ok(Self::Binary(value.to_be_bytes().to_vec()))
    }
    pub fn from_u_long(value: u64) -> Result<Self, Error> {
        Ok(Self::Binary(value.to_be_bytes().to_vec()))
    }
    pub fn from_real_with_double(value: f64) -> Result<Self, Error> {
        Ok(Self::Real(value))
    }
    pub fn from_real_with_single(value: f32) -> Result<Self, Error> {
        Ok(Self::Real(f64::from(value)))
    }
    pub fn from_string(value: String) -> Result<Self, Error> {
        Ok(Self::String(value))
    }
    pub fn from_uuid(value: UUID) -> Result<Self, Error> {
        Ok(Self::UUID(value))
    }
    pub fn from_date(value: SystemTime) -> Result<Self, Error> {
        Ok(Self::Date(value))
    }
    pub fn from_uri(value: Uri) -> Result<Self, Error> {
        Ok(Self::Uri(value))
    }
    pub fn from_binary(value: Vec<u8>) -> Result<Self, Error> {
        Ok(Self::Binary(value))
    }

    pub fn from_vector2(value: Vector2) -> Result<Self, Error> {
        Ok(Self::Array(vec![
            Self::Real(f64::from(value.x)),
            Self::Real(f64::from(value.y)),
        ]))
    }
    pub fn from_vector3(value: Vector3) -> Result<Self, Error> {
        Ok(Self::Array(vec![
            Self::Real(f64::from(value.x)),
            Self::Real(f64::from(value.y)),
            Self::Real(f64::from(value.z)),
        ]))
    }
    pub fn from_vector3d(value: Vector3d) -> Result<Self, Error> {
        Ok(Self::Array(vec![
            Self::Real(value.x),
            Self::Real(value.y),
            Self::Real(value.z),
        ]))
    }
    pub fn from_vector4(value: Vector4) -> Result<Self, Error> {
        Ok(Self::Array(vec![
            Self::Real(f64::from(value.x)),
            Self::Real(f64::from(value.y)),
            Self::Real(f64::from(value.z)),
            Self::Real(f64::from(value.w)),
        ]))
    }
    pub fn from_quaternion(value: Quaternion) -> Result<Self, Error> {
        Ok(Self::Array(vec![
            Self::Real(f64::from(value.x)),
            Self::Real(f64::from(value.y)),
            Self::Real(f64::from(value.z)),
            Self::Real(f64::from(value.w)),
        ]))
    }
    pub fn from_color4(value: Color4) -> Result<Self, Error> {
        Ok(Self::Array(vec![
            Self::Real(f64::from(value.r)),
            Self::Real(f64::from(value.g)),
            Self::Real(f64::from(value.b)),
            Self::Real(f64::from(value.a)),
        ]))
    }

    pub fn from_object(value: Object) -> Result<Self, Error> {
        object_to_osd(value)
    }

    pub fn to_object(type_: TypeId, value: Self) -> Result<Object, Error> {
        let name = type_.0;
        Ok(match name {
            "System.String" | "string" => Object::String(value.as_string()?),
            "System.Boolean" | "bool" => Object::Boolean(value.as_boolean()?),
            "System.Int32" | "int" => Object::Integer(value.as_integer()?),
            "System.UInt32" | "uint" => Object::UInteger(value.as_u_integer()?),
            "System.Int64" | "long" => Object::Long(value.as_long()?),
            "System.UInt64" | "ulong" => Object::ULong(value.as_u_long()?),
            "System.Single" | "float" | "System.Double" | "double" => {
                Object::Real(value.as_real()?)
            }
            "LibreMetaverse.UUID" | "UUID" => Object::UUID(value.as_uuid()?),
            "LibreMetaverse.Vector2" | "Vector2" => Object::Vector2(value.as_vector2()?),
            "LibreMetaverse.Vector3" | "Vector3" => Object::Vector3(value.as_vector3()?),
            "LibreMetaverse.Vector3d" | "Vector3d" => Object::Vector3d(value.as_vector3d()?),
            "LibreMetaverse.Vector4" | "Vector4" => Object::Vector4(value.as_vector4()?),
            "LibreMetaverse.Quaternion" | "Quaternion" => {
                Object::Quaternion(value.as_quaternion()?)
            }
            "LibreMetaverse.Color4" | "Color4" => Object::Color4(value.as_color4()?),
            _ => osd_to_object(value)?,
        })
    }

    pub fn serialize_members(obj: Object) -> Result<OSDMap, Error> {
        match obj {
            Object::Map(values) => OSDMap::new_with_dictionary(
                values
                    .into_iter()
                    .map(|(key, value)| Ok((key, object_to_osd(value)?)))
                    .collect::<Result<_, Error>>()?,
            ),
            value => {
                let map = OSDMap::new_with_int32(1)?;
                map.add_with_string_osd("value".to_owned(), object_to_osd(value)?)?;
                Ok(map)
            }
        }
    }

    pub fn deserialize_members(obj: &mut Object, serialized: OSDMap) -> Result<(), Error> {
        if matches!(obj, Object::Map(_)) {
            *obj = Object::Map(
                serialized
                    .snapshot()
                    .into_iter()
                    .map(|(key, value)| Ok((key, osd_to_object(value)?)))
                    .collect::<Result<_, Error>>()?,
            );
        } else if let Some(value) = serialized.get("value") {
            *obj = osd_to_object(value)?;
        }
        Ok(())
    }

    pub fn to_string(&self) -> String {
        model_text(self)
    }

    pub const fn type_(&self) -> OSDType {
        match self {
            Self::Undefined => OSDType::Unknown,
            Self::Boolean(_) => OSDType::Boolean,
            Self::Integer(_) => OSDType::Integer,
            Self::Real(_) => OSDType::Real,
            Self::String(_) => OSDType::String,
            Self::UUID(_) => OSDType::UUID,
            Self::Date(_) => OSDType::Date,
            Self::Uri(_) => OSDType::URI,
            Self::Binary(_) => OSDType::Binary,
            Self::Map(_) => OSDType::Map,
            Self::Array(_) => OSDType::Array,
            Self::LlsdXml(_) => OSDType::LlsdXml,
        }
    }

    pub fn from_with_color4(value: Color4) -> Self {
        Self::from_color4(value).expect("infallible conversion")
    }
    pub fn from_with_quaternion(value: Quaternion) -> Self {
        Self::from_quaternion(value).expect("infallible conversion")
    }
    pub fn from_with_uuid(value: UUID) -> Self {
        Self::UUID(value)
    }
    pub fn from_with_vector2(value: Vector2) -> Self {
        Self::from_vector2(value).expect("infallible conversion")
    }
    pub fn from_with_vector3(value: Vector3) -> Self {
        Self::from_vector3(value).expect("infallible conversion")
    }
    pub fn from_with_vector3d(value: Vector3d) -> Self {
        Self::from_vector3d(value).expect("infallible conversion")
    }
    pub fn from_with_vector4(value: Vector4) -> Self {
        Self::from_vector4(value).expect("infallible conversion")
    }
    pub const fn from_with_boolean(value: bool) -> Self {
        Self::Boolean(value)
    }
    pub const fn from_with_byte(value: u8) -> Self {
        Self::Integer(value as i32)
    }
    pub fn from_with_bytes(value: Vec<u8>) -> Self {
        Self::Binary(value)
    }
    pub fn from_with_date_time(value: SystemTime) -> Self {
        Self::Date(value)
    }
    pub const fn from_with_double(value: f64) -> Self {
        Self::Real(value)
    }
    pub const fn from_with_int16(value: i16) -> Self {
        Self::Integer(value as i32)
    }
    pub const fn from_with_int32(value: i32) -> Self {
        Self::Integer(value)
    }
    pub fn from_with_int64(value: i64) -> Self {
        Self::Binary(value.to_be_bytes().to_vec())
    }
    pub const fn from_with_s_byte(value: i8) -> Self {
        Self::Integer(value as i32)
    }
    pub const fn from_with_single(value: f32) -> Self {
        Self::Real(value as f64)
    }
    pub fn from_with_string(value: String) -> Self {
        Self::String(value)
    }
    pub const fn from_with_u_int16(value: u16) -> Self {
        Self::Integer(value as i32)
    }
    pub const fn from_with_u_int32(value: u32) -> Self {
        Self::Integer(value as i32)
    }
    pub fn from_with_u_int64(value: u64) -> Self {
        Self::Binary(value.to_be_bytes().to_vec())
    }
    pub fn from_with_uri(value: Uri) -> Self {
        Self::Uri(value)
    }

    pub fn from_with_osd(value: Self) -> Color4 {
        value.as_color4().unwrap_or_else(|_| Color4::black())
    }
    pub fn from_with_osd_b8ef4612(value: Self) -> Quaternion {
        value
            .as_quaternion()
            .unwrap_or_else(|_| Quaternion::identity())
    }
    pub fn from_with_osd_eba15316(value: Self) -> UUID {
        value.as_uuid().unwrap_or_else(|_| UUID::zero())
    }
    pub fn from_with_osd_e9aee905(value: Self) -> Vector2 {
        value.as_vector2().unwrap_or_else(|_| Vector2::zero())
    }
    pub fn from_with_osd_93c123bc(value: Self) -> Vector3 {
        value.as_vector3().unwrap_or_else(|_| Vector3::zero())
    }
    pub fn from_with_osd_d799abcc(value: Self) -> Vector3d {
        value.as_vector3d().unwrap_or_else(|_| Vector3d::zero())
    }
    pub fn from_with_osd_866cd1d2(value: Self) -> Vector4 {
        value.as_vector4().unwrap_or_else(|_| Vector4::zero())
    }
    pub fn from_with_osd_f50c5016(value: Self) -> bool {
        value.as_boolean().unwrap_or(false)
    }
    pub fn from_with_osd_ffa78bdc(value: Self) -> Vec<u8> {
        value.as_binary().unwrap_or_default()
    }
    pub fn from_with_osd_37aede2f(value: Self) -> SystemTime {
        value.as_date().unwrap_or(UNIX_EPOCH)
    }
    pub fn from_with_osd_1b5df47b(value: Self) -> f64 {
        value.as_real().unwrap_or(0.0)
    }
    pub fn from_with_osd_0d6b9c45(value: Self) -> i32 {
        value.as_integer().unwrap_or(0)
    }
    pub fn from_with_osd_75ba279e(value: Self) -> i64 {
        value.as_long().unwrap_or(0)
    }
    pub fn from_with_osd_232c9960(value: Self) -> f32 {
        value.as_real().unwrap_or(0.0) as f32
    }
    pub fn from_with_osd_853f4d5d(value: Self) -> String {
        value.as_string().unwrap_or_default()
    }
    pub fn from_with_osd_6a01d439(value: Self) -> u32 {
        value.as_u_integer().unwrap_or(0)
    }
    pub fn from_with_osd_1ae3c138(value: Self) -> u64 {
        value.as_u_long().unwrap_or(0)
    }
    pub fn from_with_osd_8dbb79ec(value: Self) -> Option<Uri> {
        value.as_uri().unwrap_or(None)
    }
}

/// Format-neutral parser/serializer namespace matching the C# static type.
pub struct OSDParser;

macro_rules! scalar_wrapper {
    ($name:ident, $value:ty, $variant:ident, $kind:ident) => {
        #[derive(Clone, Debug)]
        pub struct $name {
            value: $value,
        }
        impl $name {
            pub fn new(value: $value) -> Result<Self, Error> {
                Ok(Self { value })
            }
            pub fn copy(&self) -> Result<OSD, Error> {
                Ok(OSD::$variant(self.value.clone()))
            }
            pub fn type_(&self) -> OSDType {
                OSDType::$kind
            }
            pub fn to_string(&self) -> String {
                OSD::$variant(self.value.clone()).to_string()
            }
        }
    };
}

scalar_wrapper!(OSDBoolean, bool, Boolean, Boolean);
impl OSDBoolean {
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        OSD::Boolean(self.value).as_binary()
    }
    pub const fn as_boolean(&self) -> Result<bool, Error> {
        Ok(self.value)
    }
    pub fn as_integer(&self) -> Result<i32, Error> {
        Ok(i32::from(self.value))
    }
    pub fn as_real(&self) -> Result<f64, Error> {
        Ok(f64::from(u8::from(self.value)))
    }
    pub fn as_string(&self) -> Result<String, Error> {
        OSD::Boolean(self.value).as_string()
    }
}

scalar_wrapper!(OSDInteger, i32, Integer, Integer);
impl OSDInteger {
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(self.value.to_be_bytes().to_vec())
    }
    pub const fn as_boolean(&self) -> Result<bool, Error> {
        Ok(self.value != 0)
    }
    pub const fn as_integer(&self) -> Result<i32, Error> {
        Ok(self.value)
    }
    pub fn as_long(&self) -> Result<i64, Error> {
        Ok(i64::from(self.value))
    }
    pub fn as_real(&self) -> Result<f64, Error> {
        Ok(f64::from(self.value))
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(self.value.to_string())
    }
    pub fn as_u_integer(&self) -> Result<u32, Error> {
        Ok(self.value as u32)
    }
    pub fn as_u_long(&self) -> Result<u64, Error> {
        Ok(self.value as u64)
    }
}

scalar_wrapper!(OSDReal, f64, Real, Real);
impl OSDReal {
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(self.value.to_be_bytes().to_vec())
    }
    pub fn as_boolean(&self) -> Result<bool, Error> {
        OSD::Real(self.value).as_boolean()
    }
    pub fn as_integer(&self) -> Result<i32, Error> {
        Ok(real_to_i32(self.value))
    }
    pub fn as_long(&self) -> Result<i64, Error> {
        Ok(real_to_i64(self.value))
    }
    pub const fn as_real(&self) -> Result<f64, Error> {
        Ok(self.value)
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(format_real_for_codec(self.value))
    }
    pub fn as_u_integer(&self) -> Result<u32, Error> {
        Ok(real_to_u32(self.value))
    }
    pub fn as_u_long(&self) -> Result<u64, Error> {
        Ok(real_to_u64(self.value))
    }
}

scalar_wrapper!(OSDString, String, String, String);
impl OSDString {
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(self.value.as_bytes().to_vec())
    }
    pub fn as_boolean(&self) -> Result<bool, Error> {
        Ok(string_as_boolean(&self.value))
    }
    pub fn as_date(&self) -> Result<SystemTime, Error> {
        Ok(parse_system_time_for_codec(&self.value).unwrap_or(UNIX_EPOCH))
    }
    pub fn as_integer(&self) -> Result<i32, Error> {
        Ok(string_to_f64(&self.value).map_or(0, floor_to_i32))
    }
    pub fn as_long(&self) -> Result<i64, Error> {
        Ok(string_to_f64(&self.value).map_or(0, floor_to_i64))
    }
    pub fn as_real(&self) -> Result<f64, Error> {
        Ok(string_to_f64(&self.value).unwrap_or(0.0))
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(self.value.clone())
    }
    pub fn as_u_integer(&self) -> Result<u32, Error> {
        Ok(string_to_f64(&self.value).map_or(0, floor_to_u32))
    }
    pub fn as_u_long(&self) -> Result<u64, Error> {
        Ok(string_to_f64(&self.value).map_or(0, floor_to_u64))
    }
    pub fn as_uuid(&self) -> Result<UUID, Error> {
        OSD::String(self.value.clone()).as_uuid()
    }
    pub fn as_uri(&self) -> Result<Option<Uri>, Error> {
        OSD::String(self.value.clone()).as_uri()
    }
}

scalar_wrapper!(OSDUUID, UUID, UUID, UUID);
impl OSDUUID {
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        self.value.get_bytes()
    }
    pub fn as_boolean(&self) -> Result<bool, Error> {
        Ok(self.value != UUID::zero())
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(self.value.to_string())
    }
    pub const fn as_uuid(&self) -> Result<UUID, Error> {
        Ok(self.value)
    }
}

scalar_wrapper!(OSDDate, SystemTime, Date, Date);
impl OSDDate {
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(unix_seconds_for_codec(self.value).to_le_bytes().to_vec())
    }
    pub const fn as_date(&self) -> Result<SystemTime, Error> {
        Ok(self.value)
    }
    pub fn as_integer(&self) -> Result<i32, Error> {
        Ok(unix_seconds_u32(self.value) as i32)
    }
    pub fn as_long(&self) -> Result<i64, Error> {
        Ok(i64::from(unix_seconds_u32(self.value)))
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(format_system_time_for_codec(self.value))
    }
    pub fn as_u_integer(&self) -> Result<u32, Error> {
        Ok(unix_seconds_u32(self.value))
    }
    pub fn as_u_long(&self) -> Result<u64, Error> {
        Ok(u64::from(unix_seconds_u32(self.value)))
    }
}

#[derive(Clone, Debug)]
pub struct OSDUri {
    value: Uri,
}
impl OSDUri {
    pub fn new(uri: Uri) -> Result<Self, Error> {
        Ok(Self { value: uri })
    }
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(self.value.0.as_bytes().to_vec())
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(self.value.0.clone())
    }
    pub fn as_uri(&self) -> Result<Uri, Error> {
        Ok(self.value.clone())
    }
    pub fn copy(&self) -> Result<OSD, Error> {
        Ok(OSD::Uri(self.value.clone()))
    }
    pub fn to_string(&self) -> String {
        self.value.0.clone()
    }
    pub const fn type_(&self) -> OSDType {
        OSDType::URI
    }
}

#[derive(Clone, Debug)]
pub struct OSDLlsdXml {
    pub value: String,
}
impl OSDLlsdXml {
    pub fn new(value: String) -> Result<Self, Error> {
        Ok(Self { value })
    }
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(self.value.as_bytes().to_vec())
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(self.value.clone())
    }
    pub fn copy(&self) -> Result<OSD, Error> {
        Ok(OSD::LlsdXml(self.value.clone()))
    }
    pub fn to_string(&self) -> String {
        self.value.clone()
    }
    pub const fn type_(&self) -> OSDType {
        OSDType::LlsdXml
    }
}

#[derive(Clone, Debug)]
pub struct OSDBinary {
    value: Vec<u8>,
}
impl OSDBinary {
    pub fn new_with_bytes(value: Vec<u8>) -> Result<Self, Error> {
        Ok(Self { value })
    }
    pub fn new_with_int64(value: i64) -> Result<Self, Error> {
        Ok(Self {
            value: value.to_be_bytes().to_vec(),
        })
    }
    pub fn new_with_u_int32(value: u32) -> Result<Self, Error> {
        Ok(Self {
            value: value.to_be_bytes().to_vec(),
        })
    }
    pub fn new_with_u_int64(value: u64) -> Result<Self, Error> {
        Ok(Self {
            value: value.to_be_bytes().to_vec(),
        })
    }
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        Ok(self.value.clone())
    }
    pub fn as_long(&self) -> Result<i64, Error> {
        read_i64(&self.value)
    }
    pub fn as_string(&self) -> Result<String, Error> {
        Ok(base64::engine::general_purpose::STANDARD.encode(&self.value))
    }
    pub fn as_u_integer(&self) -> Result<u32, Error> {
        read_u32(&self.value)
    }
    pub fn as_u_long(&self) -> Result<u64, Error> {
        read_u64(&self.value)
    }
    pub fn copy(&self) -> Result<OSD, Error> {
        Ok(OSD::Binary(self.value.clone()))
    }
    pub fn to_string(&self) -> String {
        self.value
            .iter()
            .map(|byte| format!("{byte:02X}"))
            .collect()
    }
    pub const fn type_(&self) -> OSDType {
        OSDType::Binary
    }
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct OSDException {
    pub message: String,
    pub inner_exception: Option<ExternalError>,
}
impl OSDException {
    pub fn new_with_constructor() -> Result<Self, Error> {
        Ok(Self::default())
    }
    pub fn new_with_string(message: String) -> Result<Self, Error> {
        Ok(Self {
            message,
            inner_exception: None,
        })
    }
    pub fn new_with_string_exception(
        message: String,
        inner_exception: ExternalError,
    ) -> Result<Self, Error> {
        Ok(Self {
            message,
            inner_exception: Some(inner_exception),
        })
    }
}

/// Mutable OSD sequence with C#-compatible indexing and conversion behavior.
///
/// Reads and [`Self::copy`] return owned structural snapshots. Mutation is
/// synchronized, but callers should not infer transactional behavior across
/// multiple calls.
pub struct OSDArray {
    values: RwLock<Vec<OSD>>,
}
impl Clone for OSDArray {
    fn clone(&self) -> Self {
        Self {
            values: RwLock::new(self.snapshot()),
        }
    }
}
impl OSDArray {
    pub fn new_with_constructor() -> Result<Self, Error> {
        Ok(Self {
            values: RwLock::new(Vec::new()),
        })
    }
    pub fn new_with_list(value: Vec<OSD>) -> Result<Self, Error> {
        Ok(Self {
            values: RwLock::new(value),
        })
    }
    pub fn new_with_int32(capacity: i32) -> Result<Self, Error> {
        let capacity = usize::try_from(capacity).map_err(|_| Error::Argument)?;
        Ok(Self {
            values: RwLock::new(Vec::with_capacity(capacity)),
        })
    }
    fn read(&self) -> RwLockReadGuard<'_, Vec<OSD>> {
        self.values
            .read()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
    }
    fn write(&self) -> RwLockWriteGuard<'_, Vec<OSD>> {
        self.values
            .write()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
    }
    pub fn snapshot(&self) -> Vec<OSD> {
        self.read().clone()
    }
    pub fn add(&self, llsd: OSD) -> Result<(), Error> {
        self.write().push(llsd);
        Ok(())
    }
    pub fn as_binary(&self) -> Result<Vec<u8>, Error> {
        OSD::Array(self.snapshot()).as_binary()
    }
    pub fn as_boolean(&self) -> Result<bool, Error> {
        Ok(!self.read().is_empty())
    }
    pub fn as_color4(&self) -> Result<Color4, Error> {
        OSD::Array(self.snapshot()).as_color4()
    }
    pub fn as_long(&self) -> Result<i64, Error> {
        OSD::Array(self.snapshot()).as_long()
    }
    pub fn as_quaternion(&self) -> Result<Quaternion, Error> {
        OSD::Array(self.snapshot()).as_quaternion()
    }
    pub fn as_u_integer(&self) -> Result<u32, Error> {
        OSD::Array(self.snapshot()).as_u_integer()
    }
    pub fn as_u_long(&self) -> Result<u64, Error> {
        OSD::Array(self.snapshot()).as_u_long()
    }
    pub fn as_vector2(&self) -> Result<Vector2, Error> {
        OSD::Array(self.snapshot()).as_vector2()
    }
    pub fn as_vector3(&self) -> Result<Vector3, Error> {
        OSD::Array(self.snapshot()).as_vector3()
    }
    pub fn as_vector3d(&self) -> Result<Vector3d, Error> {
        OSD::Array(self.snapshot()).as_vector3d()
    }
    pub fn as_vector4(&self) -> Result<Vector4, Error> {
        OSD::Array(self.snapshot()).as_vector4()
    }
    pub fn clear(&self) -> Result<(), Error> {
        self.write().clear();
        Ok(())
    }
    pub fn contains_with_osd(&self, llsd: OSD) -> Result<bool, Error> {
        Ok(self.read().contains(&llsd))
    }
    pub fn contains_with_string(&self, element: String) -> Result<bool, Error> {
        Ok(self
            .read()
            .iter()
            .any(|value| matches!(value, OSD::String(text) if text == &element)))
    }
    pub fn copy(&self) -> Result<OSD, Error> {
        Ok(OSD::Array(self.snapshot()))
    }
    pub fn copy_to(&self, array: &mut [OSD], index: i32) -> Result<(), Error> {
        let index = usize::try_from(index).map_err(|_| Error::Argument)?;
        let values = self.read();
        let destination = array
            .get_mut(index..index.checked_add(values.len()).ok_or(Error::Argument)?)
            .ok_or(Error::Argument)?;
        destination.clone_from_slice(&values);
        Ok(())
    }
    pub fn index_of(&self, item: OSD) -> Result<i32, Error> {
        Ok(self
            .read()
            .iter()
            .position(|value| value == &item)
            .map_or(-1, |index| index as i32))
    }
    pub fn insert(&self, index: i32, item: OSD) -> Result<(), Error> {
        let index = usize::try_from(index).map_err(|_| Error::IndexOutOfRange)?;
        let mut values = self.write();
        if index > values.len() {
            return Err(Error::IndexOutOfRange);
        }
        values.insert(index, item);
        Ok(())
    }
    pub fn remove(&self, llsd: OSD) -> Result<bool, Error> {
        let mut values = self.write();
        if let Some(index) = values.iter().position(|value| value == &llsd) {
            values.remove(index);
            Ok(true)
        } else {
            Ok(false)
        }
    }
    pub fn remove_at(&self, index: i32) -> Result<(), Error> {
        let index = usize::try_from(index).map_err(|_| Error::IndexOutOfRange)?;
        let mut values = self.write();
        if index >= values.len() {
            return Err(Error::IndexOutOfRange);
        }
        values.remove(index);
        Ok(())
    }
    pub fn to_array_list(&self) -> Result<ArrayList, Error> {
        Ok(ArrayList(
            self.snapshot()
                .into_iter()
                .map(osd_to_object)
                .collect::<Result<_, _>>()?,
        ))
    }
    pub fn to_string(&self) -> String {
        model_text(&OSD::Array(self.snapshot()))
    }
    pub fn count(&self) -> i32 {
        self.read().len() as i32
    }
    pub const fn is_read_only(&self) -> bool {
        false
    }
    pub fn item(&self, index: i32) -> OSD {
        self.read()[usize::try_from(index).expect("negative OSDArray index")].clone()
    }
    pub fn set_item(&mut self, index: i32, value: OSD) {
        self.write()[usize::try_from(index).expect("negative OSDArray index")] = value;
    }
    pub const fn type_(&self) -> OSDType {
        OSDType::Array
    }
}

/// Mutable string-keyed OSD map.
///
/// Missing index lookups return [`OSD::Undefined`], duplicate `add` operations
/// fail, and setters replace existing values. Key, value, copy, and conversion
/// results are owned snapshots. The public map has no iteration-order promise;
/// snapshot helpers sort keys when a stable order is useful.
pub struct OSDMap {
    values: RwLock<HashMap<String, OSD>>,
}
impl Clone for OSDMap {
    fn clone(&self) -> Self {
        Self {
            values: RwLock::new(self.snapshot()),
        }
    }
}
impl OSDMap {
    pub fn new_with_constructor() -> Result<Self, Error> {
        Ok(Self {
            values: RwLock::new(HashMap::new()),
        })
    }
    pub fn new_with_dictionary(value: HashMap<String, OSD>) -> Result<Self, Error> {
        Ok(Self {
            values: RwLock::new(value),
        })
    }
    pub fn new_with_int32(capacity: i32) -> Result<Self, Error> {
        let capacity = usize::try_from(capacity).map_err(|_| Error::Argument)?;
        Ok(Self {
            values: RwLock::new(HashMap::with_capacity(capacity)),
        })
    }
    fn read(&self) -> RwLockReadGuard<'_, HashMap<String, OSD>> {
        self.values
            .read()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
    }
    fn write(&self) -> RwLockWriteGuard<'_, HashMap<String, OSD>> {
        self.values
            .write()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
    }
    pub fn snapshot(&self) -> HashMap<String, OSD> {
        self.read().clone()
    }
    pub fn get(&self, key: &str) -> Option<OSD> {
        self.read().get(key).cloned()
    }
    pub fn add_with_key_value_pair(&self, kvp: (String, OSD)) -> Result<(), Error> {
        self.add_with_string_osd(kvp.0, kvp.1)
    }
    pub fn add_with_string_osd(&self, key: String, llsd: OSD) -> Result<(), Error> {
        let mut values = self.write();
        if values.contains_key(&key) {
            return Err(Error::Argument);
        }
        values.insert(key, llsd);
        Ok(())
    }
    pub fn as_boolean(&self) -> Result<bool, Error> {
        Ok(!self.read().is_empty())
    }
    pub fn clear(&self) -> Result<(), Error> {
        self.write().clear();
        Ok(())
    }
    pub fn contains(&self, kvp: (String, OSD)) -> Result<bool, Error> {
        Ok(self.read().get(&kvp.0) == Some(&kvp.1))
    }
    pub fn contains_key(&self, key: String) -> Result<bool, Error> {
        Ok(self.read().contains_key(&key))
    }
    pub fn copy(&self) -> Result<OSD, Error> {
        Ok(OSD::Map(self.snapshot()))
    }
    pub fn copy_to(&self, array: &mut [(String, OSD)], index: i32) -> Result<(), Error> {
        let index = usize::try_from(index).map_err(|_| Error::Argument)?;
        let mut entries: Vec<_> = self.snapshot().into_iter().collect();
        entries.sort_unstable_by_key(|(key, _)| key.clone());
        let destination = array
            .get_mut(index..index.checked_add(entries.len()).ok_or(Error::Argument)?)
            .ok_or(Error::Argument)?;
        destination.clone_from_slice(&entries);
        Ok(())
    }
    pub const fn get_enumerator(&self) -> Result<IDictionaryEnumerator, Error> {
        Ok(IDictionaryEnumerator)
    }
    pub fn remove_with_key_value_pair(&self, kvp: (String, OSD)) -> Result<bool, Error> {
        Ok(self.write().remove(&kvp.0).is_some())
    }
    pub fn remove_with_string(&self, key: String) -> Result<bool, Error> {
        Ok(self.write().remove(&key).is_some())
    }
    pub fn to_hashtable(&self) -> Result<Hashtable, Error> {
        Ok(Hashtable(
            self.snapshot()
                .into_iter()
                .map(|(key, value)| Ok((Object::String(key), osd_to_object(value)?)))
                .collect::<Result<_, Error>>()?,
        ))
    }
    pub fn to_string(&self) -> String {
        model_text(&OSD::Map(self.snapshot()))
    }
    pub fn try_get_value(&self, key: String, llsd: &mut OSD) -> bool {
        if let Some(value) = self.get(&key) {
            *llsd = value;
            true
        } else {
            false
        }
    }
    pub fn count(&self) -> i32 {
        self.read().len() as i32
    }
    pub const fn is_read_only(&self) -> bool {
        false
    }
    pub fn item(&self, key: String) -> OSD {
        self.get(&key).unwrap_or_default()
    }
    pub fn set_item(&mut self, key: String, value: OSD) {
        self.write().insert(key, value);
    }
    pub fn keys(&self) -> Vec<String> {
        let mut keys: Vec<_> = self.read().keys().cloned().collect();
        keys.sort_unstable();
        keys
    }
    pub const fn type_(&self) -> OSDType {
        OSDType::Map
    }
    pub fn values(&self) -> Vec<OSD> {
        let mut entries: Vec<_> = self
            .read()
            .iter()
            .map(|(key, value)| (key.clone(), value.clone()))
            .collect();
        entries.sort_unstable_by(|(left, _), (right, _)| left.cmp(right));
        entries.into_iter().map(|(_, value)| value).collect()
    }
}

fn read_u32(bytes: &[u8]) -> Result<u32, Error> {
    Ok(u32::from_be_bytes(
        bytes
            .get(..4)
            .ok_or(Error::IndexOutOfRange)?
            .try_into()
            .map_err(|_| Error::IndexOutOfRange)?,
    ))
}
fn read_i64(bytes: &[u8]) -> Result<i64, Error> {
    Ok(i64::from_be_bytes(
        bytes
            .get(..8)
            .ok_or(Error::IndexOutOfRange)?
            .try_into()
            .map_err(|_| Error::IndexOutOfRange)?,
    ))
}
fn read_u64(bytes: &[u8]) -> Result<u64, Error> {
    Ok(u64::from_be_bytes(
        bytes
            .get(..8)
            .ok_or(Error::IndexOutOfRange)?
            .try_into()
            .map_err(|_| Error::IndexOutOfRange)?,
    ))
}
fn string_as_boolean(value: &str) -> bool {
    !value.is_empty() && value != "0" && !value.eq_ignore_ascii_case("false")
}
fn string_to_f64(value: &str) -> Option<f64> {
    value.trim().parse().ok()
}
fn floor_to_i32(value: f64) -> i32 {
    if value.is_nan() {
        0
    } else {
        value
            .floor()
            .clamp(f64::from(i32::MIN), f64::from(i32::MAX)) as i32
    }
}
fn floor_to_u32(value: f64) -> u32 {
    if value.is_nan() {
        0
    } else {
        value.floor().clamp(0.0, f64::from(u32::MAX)) as u32
    }
}
fn floor_to_i64(value: f64) -> i64 {
    if value.is_nan() {
        0
    } else if value <= i64::MIN as f64 {
        i64::MIN
    } else if value >= i64::MAX as f64 {
        i64::MAX
    } else {
        value.floor() as i64
    }
}
fn floor_to_u64(value: f64) -> u64 {
    if value.is_nan() || value <= 0.0 {
        0
    } else if value >= u64::MAX as f64 {
        u64::MAX
    } else {
        value.floor() as u64
    }
}
fn real_to_i32(value: f64) -> i32 {
    if value.is_nan() {
        0
    } else {
        value
            .round_ties_even()
            .clamp(f64::from(i32::MIN), f64::from(i32::MAX)) as i32
    }
}
fn real_to_u32(value: f64) -> u32 {
    if value.is_nan() {
        0
    } else {
        value.round_ties_even().clamp(0.0, f64::from(u32::MAX)) as u32
    }
}
fn real_to_i64(value: f64) -> i64 {
    if value.is_nan() {
        0
    } else if value <= i64::MIN as f64 {
        i64::MIN
    } else if value >= i64::MAX as f64 {
        i64::MAX
    } else {
        value.round_ties_even() as i64
    }
}
fn real_to_u64(value: f64) -> u64 {
    if value.is_nan() || value <= 0.0 {
        0
    } else if value > u64::MAX as f64 {
        i32::MAX as u64
    } else {
        value.round_ties_even() as u64
    }
}
pub(crate) fn format_real_for_codec(value: f64) -> String {
    if value.is_nan() {
        "NaN".to_owned()
    } else if value == f64::INFINITY {
        "Infinity".to_owned()
    } else if value == f64::NEG_INFINITY {
        "-Infinity".to_owned()
    } else {
        value.to_string()
    }
}
pub(crate) fn unix_seconds_for_codec(value: SystemTime) -> f64 {
    match value.duration_since(UNIX_EPOCH) {
        Ok(duration) => duration.as_secs_f64(),
        Err(error) => -error.duration().as_secs_f64(),
    }
}
fn unix_seconds_u32(value: SystemTime) -> u32 {
    match value.duration_since(UNIX_EPOCH) {
        Ok(duration) => duration.as_secs() as u32,
        Err(error) => (-(error.duration().as_secs() as i64)) as u32,
    }
}

pub(crate) fn format_system_time_for_codec(value: SystemTime) -> String {
    let (whole, nanos) = match value.duration_since(UNIX_EPOCH) {
        Ok(duration) => (duration.as_secs() as i64, duration.subsec_nanos()),
        Err(error) => {
            let duration = error.duration();
            if duration.subsec_nanos() == 0 {
                (-(duration.as_secs() as i64), 0)
            } else {
                (
                    -(duration.as_secs() as i64) - 1,
                    1_000_000_000 - duration.subsec_nanos(),
                )
            }
        }
    };
    let hundredths = (nanos / 10_000_000) as u8;
    let (year, month, day, hour, minute, second) = civil_from_unix(whole);
    if nanos / 1_000_000 > 0 {
        format!("{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}.{hundredths:02}Z")
    } else {
        format!("{year:04}-{month:02}-{day:02}T{hour:02}:{minute:02}:{second:02}Z")
    }
}

fn civil_from_unix(seconds: i64) -> (i32, u32, u32, u32, u32, u32) {
    let days = seconds.div_euclid(86_400);
    let day_seconds = seconds.rem_euclid(86_400);
    let z = days + 719_468;
    let era = if z >= 0 { z } else { z - 146_096 }.div_euclid(146_097);
    let doe = z - era * 146_097;
    let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365;
    let mut year = yoe + era * 400;
    let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
    let mp = (5 * doy + 2) / 153;
    let day = doy - (153 * mp + 2) / 5 + 1;
    let month = mp + if mp < 10 { 3 } else { -9 };
    year += i64::from(month <= 2);
    (
        year as i32,
        month as u32,
        day as u32,
        (day_seconds / 3_600) as u32,
        ((day_seconds % 3_600) / 60) as u32,
        (day_seconds % 60) as u32,
    )
}

pub(crate) fn parse_system_time_for_codec(value: &str) -> Option<SystemTime> {
    let value = value.trim();
    let (date, time) = value.split_once('T').or_else(|| value.split_once(' '))?;
    let mut date_parts = date.split('-');
    let year: i32 = date_parts.next()?.parse().ok()?;
    let month: u32 = date_parts.next()?.parse().ok()?;
    let day: u32 = date_parts.next()?.parse().ok()?;
    if date_parts.next().is_some() || !(1..=12).contains(&month) || !(1..=31).contains(&day) {
        return None;
    }
    let time = time.strip_suffix('Z').unwrap_or(time);
    let (clock, fraction) = time.split_once('.').map_or((time, ""), |parts| parts);
    let mut time_parts = clock.split(':');
    let hour: u32 = time_parts.next()?.parse().ok()?;
    let minute: u32 = time_parts.next()?.parse().ok()?;
    let second: u32 = time_parts.next()?.parse().ok()?;
    if time_parts.next().is_some() || hour > 23 || minute > 59 || second > 59 {
        return None;
    }
    let days = days_from_civil(year, month, day)?;
    let whole = days
        .checked_mul(86_400)?
        .checked_add(i64::from(hour * 3_600 + minute * 60 + second))?;
    let nanos = if fraction.is_empty() {
        0
    } else {
        let digits = fraction.as_bytes();
        if digits.len() > 9 || !digits.iter().all(u8::is_ascii_digit) {
            return None;
        }
        fraction
            .parse::<u32>()
            .ok()?
            .checked_mul(10_u32.pow((9 - digits.len()) as u32))?
    };
    if whole >= 0 {
        UNIX_EPOCH.checked_add(Duration::new(whole as u64, nanos))
    } else if nanos == 0 {
        UNIX_EPOCH.checked_sub(Duration::from_secs(whole.unsigned_abs()))
    } else {
        UNIX_EPOCH.checked_sub(Duration::new(
            whole.unsigned_abs() - 1,
            1_000_000_000 - nanos,
        ))
    }
}

fn days_from_civil(year: i32, month: u32, day: u32) -> Option<i64> {
    let max_day = match month {
        2 if year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) => 29,
        2 => 28,
        4 | 6 | 9 | 11 => 30,
        1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
        _ => return None,
    };
    if day == 0 || day > max_day {
        return None;
    }
    let adjusted_year = i64::from(year) - i64::from(month <= 2);
    let era = adjusted_year.div_euclid(400);
    let yoe = adjusted_year - era * 400;
    let adjusted_month = i64::from(month) + if month > 2 { -3 } else { 9 };
    let doy = (153 * adjusted_month + 2) / 5 + i64::from(day) - 1;
    let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
    Some(era * 146_097 + doe - 719_468)
}

fn valid_uri_reference(value: &str) -> bool {
    !value.chars().any(char::is_whitespace) && !value.chars().any(char::is_control)
}

pub(crate) fn format_uri_for_codec(value: &str) -> String {
    if !value.contains("://") {
        return value.to_owned();
    }
    let mut output = String::with_capacity(value.len());
    for character in value.chars() {
        match character {
            ' ' => output.push_str("%20"),
            '"' => output.push_str("%22"),
            '<' => output.push_str("%3C"),
            '>' => output.push_str("%3E"),
            character if character.is_control() => {
                let mut bytes = [0_u8; 4];
                for byte in character.encode_utf8(&mut bytes).as_bytes() {
                    write!(output, "%{byte:02X}").expect("writing to String is infallible");
                }
            }
            character => output.push(character),
        }
    }
    output
}

fn escape_text(value: &str) -> String {
    let mut output = String::with_capacity(value.len() + 2);
    output.push('"');
    for character in value.chars() {
        match character {
            '"' => output.push_str("\\\""),
            '\\' => output.push_str("\\\\"),
            '\n' => output.push_str("\\n"),
            '\r' => output.push_str("\\r"),
            '\t' => output.push_str("\\t"),
            character if character.is_control() => {
                write!(output, "\\u{:04x}", character as u32)
                    .expect("writing to String is infallible");
            }
            character => output.push(character),
        }
    }
    output.push('"');
    output
}

fn model_text(value: &OSD) -> String {
    match value {
        OSD::Undefined => "undef".to_owned(),
        OSD::Boolean(_)
        | OSD::Integer(_)
        | OSD::Real(_)
        | OSD::UUID(_)
        | OSD::Date(_)
        | OSD::Uri(_)
        | OSD::Binary(_) => value.as_string().unwrap_or_default(),
        OSD::String(text) | OSD::LlsdXml(text) => text.clone(),
        OSD::Array(_) | OSD::Map(_) => json_text_with_defaults(value),
    }
}

fn json_text_with_defaults(value: &OSD) -> String {
    match value {
        OSD::Undefined => "null".to_owned(),
        OSD::Boolean(value) => value.to_string(),
        OSD::Integer(value) => value.to_string(),
        OSD::Real(value) => format_real_for_codec(*value),
        OSD::String(value) => escape_text(value),
        OSD::LlsdXml(_) => "null".to_owned(),
        OSD::UUID(_) | OSD::Date(_) | OSD::Uri(_) => {
            escape_text(&value.as_string().unwrap_or_default())
        }
        OSD::Binary(bytes) => format!(
            "[{}]",
            bytes
                .iter()
                .map(u8::to_string)
                .collect::<Vec<_>>()
                .join(",")
        ),
        OSD::Array(values) => format!(
            "[{}]",
            values
                .iter()
                .map(json_text_with_defaults)
                .collect::<Vec<_>>()
                .join(",")
        ),
        OSD::Map(values) => {
            let mut entries: Vec<_> = values.iter().collect();
            entries.sort_unstable_by_key(|(key, _)| *key);
            format!(
                "{{{}}}",
                entries
                    .into_iter()
                    .map(|(key, value)| {
                        format!("{}:{}", escape_text(key), json_text_with_defaults(value))
                    })
                    .collect::<Vec<_>>()
                    .join(",")
            )
        }
    }
}

fn object_to_osd(value: Object) -> Result<OSD, Error> {
    Ok(match value {
        Object::Undefined => OSD::Undefined,
        Object::Boolean(value) => OSD::Boolean(value),
        Object::Integer(value) => OSD::Integer(value),
        Object::UInteger(value) => OSD::Binary(value.to_be_bytes().to_vec()),
        Object::Long(value) => OSD::Binary(value.to_be_bytes().to_vec()),
        Object::ULong(value) => OSD::Binary(value.to_be_bytes().to_vec()),
        Object::Real(value) => OSD::Real(value),
        Object::String(value) => OSD::String(value),
        Object::UUID(value) => OSD::UUID(value),
        Object::Date(value) => OSD::Date(value),
        Object::Bytes(value) => OSD::Binary(value),
        Object::Uri(value) => OSD::Uri(value),
        Object::Array(values) => OSD::Array(
            values
                .into_iter()
                .map(object_to_osd)
                .collect::<Result<_, _>>()?,
        ),
        Object::Map(values) => OSD::Map(
            values
                .into_iter()
                .map(|(key, value)| Ok((key, object_to_osd(value)?)))
                .collect::<Result<_, Error>>()?,
        ),
        Object::Vector2(value) => OSD::from_vector2(value)?,
        Object::Vector3(value) => OSD::from_vector3(value)?,
        Object::Vector3d(value) => OSD::from_vector3d(value)?,
        Object::Vector4(value) => OSD::from_vector4(value)?,
        Object::Quaternion(value) => OSD::from_quaternion(value)?,
        Object::Color4(value) => OSD::from_color4(value)?,
        Object::Matrix4(_) | Object::Opaque(_) => OSD::Undefined,
    })
}

fn osd_to_object(value: OSD) -> Result<Object, Error> {
    Ok(match value {
        OSD::Undefined => Object::Undefined,
        OSD::Boolean(value) => Object::Boolean(value),
        OSD::Integer(value) => Object::Integer(value),
        OSD::Real(value) => Object::Real(value),
        OSD::String(value) | OSD::LlsdXml(value) => Object::String(value),
        OSD::UUID(value) => Object::UUID(value),
        OSD::Date(value) => Object::Date(value),
        OSD::Uri(value) => Object::Uri(value),
        OSD::Binary(value) => Object::Bytes(value),
        OSD::Array(values) => Object::Array(
            values
                .into_iter()
                .map(osd_to_object)
                .collect::<Result<_, _>>()?,
        ),
        OSD::Map(values) => Object::Map(
            values
                .into_iter()
                .map(|(key, value)| Ok((key, osd_to_object(value)?)))
                .collect::<Result<_, Error>>()?,
        ),
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::hash_map::DefaultHasher;

    #[test]
    fn scalar_conversions_match_reference_edges() {
        assert_eq!(OSD::Real(2.5).as_integer(), Ok(2));
        assert_eq!(OSD::Real(3.5).as_integer(), Ok(4));
        assert_eq!(OSD::Real(f64::NAN).as_integer(), Ok(0));
        assert_eq!(OSD::String("-1.2".into()).as_integer(), Ok(-2));
        assert_eq!(OSD::String("FALSE".into()).as_boolean(), Ok(false));
        assert_eq!(OSD::Integer(-1).as_u_integer(), Ok(u32::MAX));
    }

    #[test]
    fn binary_numeric_conversions_are_network_order() {
        let value = OSDBinary::new_with_u_int64(0x0102_0304_0506_0708).unwrap();
        assert_eq!(value.as_binary().unwrap(), vec![1, 2, 3, 4, 5, 6, 7, 8]);
        assert_eq!(value.as_u_long(), Ok(0x0102_0304_0506_0708));
        assert_eq!(
            OSDBinary::new_with_u_int32(0x0102_0304)
                .unwrap()
                .as_u_integer(),
            Ok(0x0102_0304)
        );
    }

    #[test]
    fn arrays_mutate_and_convert_without_leaking_borrows() {
        let array = OSDArray::new_with_constructor().unwrap();
        array.add(OSD::Real(1.0)).unwrap();
        array.add(OSD::Real(2.0)).unwrap();
        array.add(OSD::Real(3.0)).unwrap();
        assert_eq!(
            array.as_vector3().unwrap(),
            Vector3 {
                x: 1.0,
                y: 2.0,
                z: 3.0
            }
        );
        assert_eq!(array.count(), 3);
        assert!(array.remove(OSD::Real(2.0)).unwrap());
        assert_eq!(array.snapshot(), vec![OSD::Real(1.0), OSD::Real(3.0)]);
    }

    #[test]
    fn maps_have_undefined_index_default_and_snapshot_copy() {
        let mut map = OSDMap::new_with_constructor().unwrap();
        map.add_with_string_osd("answer".into(), OSD::Integer(42))
            .unwrap();
        assert_eq!(map.item("missing".into()), OSD::Undefined);
        assert_eq!(map.item("answer".into()), OSD::Integer(42));
        map.set_item("answer".into(), OSD::Integer(43));
        assert_eq!(map.item("answer".into()), OSD::Integer(43));
        assert!(
            map.add_with_string_osd("answer".into(), OSD::Integer(44))
                .is_err()
        );
        map.set_item(
            "values".into(),
            OSD::Array(vec![
                OSD::Boolean(true),
                OSD::String("quoted\"text".into()),
                OSD::Binary(vec![1, 2]),
                OSD::Undefined,
            ]),
        );
        assert_eq!(
            map.to_string(),
            r#"{"answer":43,"values":[true,"quoted\"text",[1,2],null]}"#
        );
    }

    #[test]
    fn structural_map_hash_is_independent_of_hashmap_iteration() {
        let left = OSD::Map(HashMap::from([
            ("a".into(), OSD::Integer(1)),
            ("b".into(), OSD::Integer(2)),
        ]));
        let right = OSD::Map(HashMap::from([
            ("b".into(), OSD::Integer(2)),
            ("a".into(), OSD::Integer(1)),
        ]));
        let hash = |value: &OSD| {
            let mut hasher = DefaultHasher::new();
            value.hash(&mut hasher);
            hasher.finish()
        };
        assert_eq!(left, right);
        assert_eq!(hash(&left), hash(&right));
    }

    #[test]
    fn nesting_limits_reject_depth_nodes_and_binary_allocation() {
        let nested = OSD::Array(vec![OSD::Array(vec![OSD::Binary(vec![0; 4])])]);
        assert_eq!(nested.validate_limits(2, 3, 4), Ok(()));
        assert_eq!(nested.validate_limits(1, 3, 4), Err(Error::Argument));
        assert_eq!(nested.validate_limits(2, 2, 4), Err(Error::Argument));
        assert_eq!(nested.validate_limits(2, 3, 3), Err(Error::Argument));
    }

    #[test]
    fn utc_dates_round_trip_reference_text_and_little_endian_binary() {
        let date = UNIX_EPOCH + Duration::new(1_704_164_645, 120_000_000);
        let osd = OSDDate::new(date).unwrap();
        assert_eq!(osd.as_string().unwrap(), "2024-01-02T03:04:05.12Z");
        assert_eq!(
            OSDString::new("2024-01-02T03:04:05.12Z".into())
                .unwrap()
                .as_date()
                .unwrap(),
            date
        );
        assert_eq!(osd.as_binary().unwrap(), 1_704_164_645.12_f64.to_le_bytes());
        let pre_epoch = OSDString::new("1969-12-31T23:59:59.50Z".into())
            .unwrap()
            .as_date()
            .unwrap();
        assert_eq!(pre_epoch, UNIX_EPOCH - Duration::from_millis(500));
        assert_eq!(
            OSDDate::new(pre_epoch).unwrap().as_string().unwrap(),
            "1969-12-31T23:59:59.50Z"
        );
        assert_eq!(
            OSDDate::new(UNIX_EPOCH + Duration::from_millis(1))
                .unwrap()
                .as_string()
                .unwrap(),
            "1970-01-01T00:00:00.00Z"
        );
        assert_eq!(
            OSDDate::new(UNIX_EPOCH - Duration::from_secs(1))
                .unwrap()
                .as_u_integer(),
            Ok(u32::MAX)
        );
    }

    #[test]
    fn object_bridge_preserves_unsigned_numeric_kinds() {
        assert_eq!(
            OSD::from_object(Object::UInteger(0xFEDC_BA98)).unwrap(),
            OSD::Binary(vec![0xFE, 0xDC, 0xBA, 0x98])
        );
        assert_eq!(
            OSD::to_object(
                TypeId("System.UInt64"),
                OSD::Binary(u64::MAX.to_be_bytes().to_vec())
            ),
            Ok(Object::ULong(u64::MAX))
        );
    }
}
