//! Project-owned replacements for external types exposed by C# signatures.
//!
//! These types preserve Rust API identity without copying external member
//! surfaces. Their behavior is implemented only when the owning API slice is
//! ported.

use std::any::Any;
use std::collections::BTreeMap;
use std::fmt;
use std::future::Future;
use std::hash::Hash;
use std::marker::PhantomData;
use std::pin::Pin;
use std::sync::{
    Arc, Mutex, Weak,
    atomic::{AtomicBool, AtomicU64, Ordering},
};
use std::task::{Context, Poll, Waker};

pub trait Collection<T> {}

pub trait ReadWrite: std::io::Read + std::io::Write + std::io::Seek {}

impl<T: std::io::Read + std::io::Write + std::io::Seek> ReadWrite for T {}

trait OpaqueValue: Any + fmt::Debug + Send + Sync {
    fn as_any(&self) -> &dyn Any;
    fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
}

impl<T: Any + fmt::Debug + Send + Sync> OpaqueValue for T {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn into_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
        self
    }
}

/// A type-erased reference value used when a mapped `System.Object` carries a
/// project type rather than one of the protocol scalar variants.
///
/// Equality and hashing use reference identity, matching the default behavior
/// of arbitrary CLR reference objects. The contained value can be recovered
/// with [`Object::downcast_ref`].
#[derive(Clone)]
pub struct OpaqueObject(Arc<dyn OpaqueValue>);

impl fmt::Debug for OpaqueObject {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter
            .debug_tuple("OpaqueObject")
            .field(&self.0)
            .finish()
    }
}

impl PartialEq for OpaqueObject {
    fn eq(&self, other: &Self) -> bool {
        Arc::ptr_eq(&self.0, &other.0)
    }
}

impl Eq for OpaqueObject {}

impl Hash for OpaqueObject {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        let pointer = Arc::as_ptr(&self.0).cast::<()>();
        pointer.hash(state);
    }
}

#[derive(Clone, Debug)]
pub enum Object {
    Undefined,
    Boolean(bool),
    Integer(i32),
    UInteger(u32),
    Long(i64),
    ULong(u64),
    Real(f64),
    Color4(crate::Color4),
    Date(std::time::SystemTime),
    Bytes(Vec<u8>),
    Uri(Uri),
    Array(Vec<Object>),
    Map(std::collections::HashMap<String, Object>),
    Matrix4(crate::Matrix4),
    Quaternion(crate::Quaternion),
    String(String),
    UUID(crate::UUID),
    Vector2(crate::Vector2),
    Vector3(crate::Vector3),
    Vector3d(crate::Vector3d),
    Vector4(crate::Vector4),
    /// A project-owned value passed through a mapped `System.Object` boundary.
    Opaque(OpaqueObject),
}

impl Object {
    /// Boxes a project-owned value for a mapped `System.Object` parameter.
    #[must_use]
    pub fn opaque<T: Any + fmt::Debug + Send + Sync>(value: T) -> Self {
        Self::Opaque(OpaqueObject(Arc::new(value)))
    }

    /// Borrows an opaque value when its concrete type is `T`.
    #[must_use]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        match self {
            Self::Opaque(value) => value.0.as_ref().as_any().downcast_ref(),
            _ => None,
        }
    }

    /// Clones the opaque reference and recovers its concrete shared value.
    #[must_use]
    pub fn downcast_arc<T: Any + Send + Sync>(&self) -> Option<Arc<T>> {
        match self {
            Self::Opaque(value) => value.0.clone().into_any().downcast().ok(),
            _ => None,
        }
    }
}

impl PartialEq for Object {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::Undefined, Self::Undefined) => true,
            (Self::Boolean(lhs), Self::Boolean(rhs)) => lhs == rhs,
            (Self::Integer(lhs), Self::Integer(rhs)) => lhs == rhs,
            (Self::UInteger(lhs), Self::UInteger(rhs)) => lhs == rhs,
            (Self::Long(lhs), Self::Long(rhs)) => lhs == rhs,
            (Self::ULong(lhs), Self::ULong(rhs)) => lhs == rhs,
            (Self::Real(lhs), Self::Real(rhs)) => lhs.to_bits() == rhs.to_bits(),
            (Self::Date(lhs), Self::Date(rhs)) => lhs == rhs,
            (Self::Bytes(lhs), Self::Bytes(rhs)) => lhs == rhs,
            (Self::Uri(lhs), Self::Uri(rhs)) => lhs == rhs,
            (Self::Array(lhs), Self::Array(rhs)) => lhs == rhs,
            (Self::Map(lhs), Self::Map(rhs)) => lhs == rhs,
            (Self::Color4(lhs), Self::Color4(rhs)) => crate::Color4::eq(*lhs, *rhs),
            (Self::Matrix4(lhs), Self::Matrix4(rhs)) => crate::Matrix4::eq(*lhs, *rhs),
            (Self::Quaternion(lhs), Self::Quaternion(rhs)) => crate::Quaternion::eq(*lhs, *rhs),
            (Self::String(lhs), Self::String(rhs)) => lhs == rhs,
            (Self::UUID(lhs), Self::UUID(rhs)) => lhs == rhs,
            (Self::Vector2(lhs), Self::Vector2(rhs)) => crate::Vector2::eq(*lhs, *rhs),
            (Self::Vector3(lhs), Self::Vector3(rhs)) => crate::Vector3::eq(*lhs, *rhs),
            (Self::Vector3d(lhs), Self::Vector3d(rhs)) => crate::Vector3d::eq(*lhs, *rhs),
            (Self::Vector4(lhs), Self::Vector4(rhs)) => crate::Vector4::eq(*lhs, *rhs),
            (Self::Opaque(lhs), Self::Opaque(rhs)) => lhs == rhs,
            _ => false,
        }
    }
}

impl Eq for Object {}

impl std::hash::Hash for Object {
    fn hash<H: std::hash::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::UInteger(value) => value.hash(state),
            Self::Long(value) => value.hash(state),
            Self::ULong(value) => value.hash(state),
            Self::Real(value) => value.to_bits().hash(state),
            Self::Date(value) => value.hash(state),
            Self::Bytes(value) => value.hash(state),
            Self::Uri(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);
            }
            Self::Color4(value) => value.get_hash_code().hash(state),
            Self::Matrix4(value) => value.get_hash_code().hash(state),
            Self::Quaternion(value) => value.get_hash_code().hash(state),
            Self::String(value) => value.hash(state),
            Self::UUID(value) => value.hash(state),
            Self::Vector2(value) => value.get_hash_code().hash(state),
            Self::Vector3(value) => value.get_hash_code().hash(state),
            Self::Vector3d(value) => value.get_hash_code().hash(state),
            Self::Vector4(value) => value.get_hash_code().hash(state),
            Self::Opaque(value) => value.hash(state),
        }
    }
}

impl From<String> for Object {
    fn from(value: String) -> Self {
        Self::String(value)
    }
}

impl From<&str> for Object {
    fn from(value: &str) -> Self {
        Self::String(value.to_owned())
    }
}

impl From<crate::Color4> for Object {
    fn from(value: crate::Color4) -> Self {
        Self::Color4(value)
    }
}
impl From<crate::Matrix4> for Object {
    fn from(value: crate::Matrix4) -> Self {
        Self::Matrix4(value)
    }
}
impl From<crate::Quaternion> for Object {
    fn from(value: crate::Quaternion) -> Self {
        Self::Quaternion(value)
    }
}
impl From<crate::Vector2> for Object {
    fn from(value: crate::Vector2) -> Self {
        Self::Vector2(value)
    }
}
impl From<crate::Vector3> for Object {
    fn from(value: crate::Vector3) -> Self {
        Self::Vector3(value)
    }
}
impl From<crate::Vector3d> for Object {
    fn from(value: crate::Vector3d) -> Self {
        Self::Vector3d(value)
    }
}
impl From<crate::Vector4> for Object {
    fn from(value: crate::Vector4) -> Self {
        Self::Vector4(value)
    }
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Utf16CodeUnit(pub u16);

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Guid(pub [u8; 16]);

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Uri(pub String);

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct Regex(pub String);

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct CultureInfo(pub String);

#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct ExternalError(pub String);

/// Type-erased enum name and optional [`crate::EnumInfoAttribute`] text.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct EnumValue {
    pub(crate) name: &'static str,
    pub(crate) text: Option<&'static str>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ArrayList(pub Vec<Object>);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Array(pub Vec<Object>);

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Hashtable(pub std::collections::HashMap<Object, Object>);

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct IDictionaryEnumerator;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct IEqualityComparer<T>(pub PhantomData<fn(T)>);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StringReader(pub String);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StreamReader(pub Vec<u8>);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct XmlTextReader(pub String);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct XmlTextWriter(pub String);

struct CancellationState {
    cancelled: AtomicBool,
    next_id: AtomicU64,
    waiters: Mutex<BTreeMap<u64, Waker>>,
    callbacks: Mutex<BTreeMap<u64, Arc<dyn Fn() + Send + Sync>>>,
}

impl Default for CancellationState {
    fn default() -> Self {
        Self {
            cancelled: AtomicBool::new(false),
            next_id: AtomicU64::new(1),
            waiters: Mutex::new(BTreeMap::new()),
            callbacks: Mutex::new(BTreeMap::new()),
        }
    }
}

/// A cheap, cloneable cancellation signal.
///
/// Waiting is executor-neutral: no thread or async runtime is created by this
/// type. Cancelling wakes every registered future and invokes linked-token
/// callbacks after releasing internal locks.
#[derive(Clone, Default)]
pub struct CancellationToken(Arc<CancellationState>);

impl fmt::Debug for CancellationToken {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter
            .debug_struct("CancellationToken")
            .field(
                "is_cancellation_requested",
                &self.is_cancellation_requested(),
            )
            .finish_non_exhaustive()
    }
}

impl CancellationToken {
    #[must_use]
    pub fn is_cancellation_requested(&self) -> bool {
        self.0.cancelled.load(Ordering::Acquire)
    }

    /// Returns a future that completes when cancellation is requested.
    #[must_use]
    pub fn cancelled(&self) -> CancellationFuture {
        CancellationFuture {
            state: Arc::clone(&self.0),
            waiter_id: None,
        }
    }

    /// Converts an observed cancellation request to the shared typed error.
    ///
    /// # Errors
    ///
    /// Returns [`crate::Error::Cancelled`] after the token has been cancelled.
    pub fn throw_if_cancellation_requested(&self) -> Result<(), crate::Error> {
        if self.is_cancellation_requested() {
            Err(crate::Error::Cancelled)
        } else {
            Ok(())
        }
    }

    /// Registers an executor-neutral callback and removes it when the returned
    /// guard is dropped.
    #[must_use = "dropping the guard immediately unregisters the callback"]
    pub fn register_callback(&self, callback: Arc<dyn Fn() + Send + Sync>) -> Subscription {
        if self.is_cancellation_requested() {
            callback();
            return Subscription::detached();
        }
        let id = self.0.next_id.fetch_add(1, Ordering::Relaxed);
        self.0
            .callbacks
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .insert(id, callback);
        if self.is_cancellation_requested() {
            if let Some(callback) = self
                .0
                .callbacks
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id)
            {
                callback();
            }
            return Subscription::detached();
        }
        let state = Arc::downgrade(&self.0);
        Subscription::new(move || {
            let Some(state) = state.upgrade() else {
                return;
            };
            state
                .callbacks
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id);
        })
    }

    fn register(&self, callback: Arc<dyn Fn() + Send + Sync>) -> CancellationRegistration {
        if self.is_cancellation_requested() {
            callback();
            return CancellationRegistration::completed();
        }

        let id = self.0.next_id.fetch_add(1, Ordering::Relaxed);
        self.0
            .callbacks
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .insert(id, callback);
        if self.is_cancellation_requested() {
            let callback = self
                .0
                .callbacks
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id);
            if let Some(callback) = callback {
                callback();
            }
            CancellationRegistration::completed()
        } else {
            CancellationRegistration {
                state: Arc::downgrade(&self.0),
                id: Some(id),
            }
        }
    }
}

/// Future returned by [`CancellationToken::cancelled`].
pub struct CancellationFuture {
    state: Arc<CancellationState>,
    waiter_id: Option<u64>,
}

impl Future for CancellationFuture {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
        if self.state.cancelled.load(Ordering::Acquire) {
            return Poll::Ready(());
        }

        let id = if let Some(id) = self.waiter_id {
            id
        } else {
            let id = self.state.next_id.fetch_add(1, Ordering::Relaxed);
            self.waiter_id = Some(id);
            id
        };
        self.state
            .waiters
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .insert(id, context.waker().clone());
        if self.state.cancelled.load(Ordering::Acquire) {
            self.state
                .waiters
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id);
            self.waiter_id = None;
            Poll::Ready(())
        } else {
            Poll::Pending
        }
    }
}

impl Drop for CancellationFuture {
    fn drop(&mut self) {
        if let Some(id) = self.waiter_id {
            self.state
                .waiters
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id);
        }
    }
}

struct CancellationRegistration {
    state: Weak<CancellationState>,
    id: Option<u64>,
}

impl CancellationRegistration {
    fn completed() -> Self {
        Self {
            state: Weak::new(),
            id: None,
        }
    }
}

impl Drop for CancellationRegistration {
    fn drop(&mut self) {
        if let (Some(state), Some(id)) = (self.state.upgrade(), self.id) {
            state
                .callbacks
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id);
        }
    }
}

/// RAII guard for a mapped event subscription.
///
/// Dropping or explicitly closing the guard invokes the removal callback once.
/// The callback normally owns only a weak reference to the event registry, so
/// an abandoned subscription cannot keep its publisher alive.
#[must_use = "dropping the subscription immediately unregisters the handler"]
pub struct Subscription {
    close: Option<Box<dyn FnOnce() + Send + Sync>>,
}

impl Subscription {
    pub fn new(close: impl FnOnce() + Send + Sync + 'static) -> Self {
        Self {
            close: Some(Box::new(close)),
        }
    }

    pub fn close(mut self) {
        if let Some(close) = self.close.take() {
            close();
        }
    }

    #[must_use]
    pub const fn is_active(&self) -> bool {
        self.close.is_some()
    }

    pub const fn detached() -> Self {
        Self { close: None }
    }
}

impl Default for Subscription {
    fn default() -> Self {
        Self::detached()
    }
}

impl fmt::Debug for Subscription {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter
            .debug_struct("Subscription")
            .field("active", &self.is_active())
            .finish()
    }
}

impl Drop for Subscription {
    fn drop(&mut self) {
        if let Some(close) = self.close.take() {
            close();
        }
    }
}

pub type EventHandler<T> = Arc<dyn Fn(T) + Send + Sync>;

pub struct DictionaryKeys<TKey, TValue>(pub Vec<TKey>, pub PhantomData<fn(TValue)>);

pub struct DictionaryEntry(pub Object, pub Object);

/// Result of a mapped rate-limit acquisition.
///
/// Token-bucket leases do not return a token when dropped; the value records
/// whether a token was acquired or the bounded waiting queue was already full.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct RateLimitLease {
    acquired: bool,
}

impl RateLimitLease {
    #[must_use]
    pub const fn acquired() -> Self {
        Self { acquired: true }
    }

    #[must_use]
    pub const fn rejected() -> Self {
        Self { acquired: false }
    }

    #[must_use]
    pub const fn is_acquired(self) -> bool {
        self.acquired
    }
}

struct CancellationSourceState {
    token: CancellationToken,
    linked_registrations: Mutex<Vec<CancellationRegistration>>,
}

/// Owns and triggers a [`CancellationToken`].
#[derive(Clone)]
pub struct CancellationTokenSource(Arc<CancellationSourceState>);

impl Default for CancellationTokenSource {
    fn default() -> Self {
        Self(Arc::new(CancellationSourceState {
            token: CancellationToken::default(),
            linked_registrations: Mutex::new(Vec::new()),
        }))
    }
}

impl fmt::Debug for CancellationTokenSource {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter
            .debug_struct("CancellationTokenSource")
            .field(
                "is_cancellation_requested",
                &self.0.token.is_cancellation_requested(),
            )
            .finish_non_exhaustive()
    }
}

impl CancellationTokenSource {
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    /// Creates a source cancelled when any parent token is cancelled.
    #[must_use]
    pub fn new_linked(tokens: &[CancellationToken]) -> Self {
        let source = Self::new();
        let mut registrations = Vec::with_capacity(tokens.len());
        for token in tokens {
            let linked = Arc::downgrade(&source.0);
            registrations.push(token.register(Arc::new(move || {
                if let Some(linked) = linked.upgrade() {
                    Self::cancel_state(&linked);
                }
            })));
        }
        *source
            .0
            .linked_registrations
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner) = registrations;
        source
    }

    #[must_use]
    pub fn token(&self) -> CancellationToken {
        self.0.token.clone()
    }

    pub fn cancel(&self) {
        Self::cancel_state(&self.0);
    }

    fn cancel_state(state: &CancellationSourceState) {
        if state.token.0.cancelled.swap(true, Ordering::AcqRel) {
            return;
        }
        let waiters = std::mem::take(
            &mut *state
                .token
                .0
                .waiters
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner),
        );
        let callbacks = std::mem::take(
            &mut *state
                .token
                .0
                .callbacks
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner),
        );
        for (_, waker) in waiters {
            waker.wake();
        }
        for (_, callback) in callbacks {
            callback();
        }
    }
}

pub trait Close {
    /// Releases the mapped disposable resource.
    ///
    /// # Errors
    ///
    /// Returns the mapped disposal error, or an unimplemented error until the
    /// owning resource supplies its implementation.
    fn close(&mut self) -> Result<(), ExternalError> {
        Err(ExternalError("Close::close is not implemented".to_owned()))
    }
}

pub struct Thread;

pub struct Task<T>(pub PhantomData<fn() -> T>);

struct TaskCompletionState<T> {
    next_id: AtomicU64,
    result: Mutex<Option<Result<T, crate::Error>>>,
    waiters: Mutex<BTreeMap<u64, Waker>>,
}

/// Cloneable completion source used by mapped task-returning APIs.
#[derive(Clone)]
pub struct TaskCompletionSource<T>(Arc<TaskCompletionState<T>>);

impl<T> TaskCompletionSource<T> {
    #[must_use]
    pub fn new() -> Self {
        Self(Arc::new(TaskCompletionState {
            next_id: AtomicU64::new(1),
            result: Mutex::new(None),
            waiters: Mutex::new(BTreeMap::new()),
        }))
    }

    /// Completes the task once and wakes every waiter.
    #[must_use]
    pub fn try_set_result(&self, value: T) -> bool {
        self.try_complete(Ok(value))
    }

    /// Completes the task with a typed failure once.
    #[must_use]
    pub fn try_set_error(&self, error: crate::Error) -> bool {
        self.try_complete(Err(error))
    }

    /// Completes the task with mapped cancellation once.
    #[must_use]
    pub fn try_set_cancelled(&self) -> bool {
        self.try_set_error(crate::Error::Cancelled)
    }

    fn try_complete(&self, value: Result<T, crate::Error>) -> bool {
        let mut result = self
            .0
            .result
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner);
        if result.is_some() {
            return false;
        }
        *result = Some(value);
        drop(result);
        for (_, waiter) in std::mem::take(
            &mut *self
                .0
                .waiters
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner),
        ) {
            waiter.wake();
        }
        true
    }

    #[must_use]
    pub fn future(&self) -> TaskCompletionFuture<T> {
        TaskCompletionFuture {
            state: Arc::clone(&self.0),
            waiter_id: None,
        }
    }

    #[must_use]
    pub fn is_completed(&self) -> bool {
        self.0
            .result
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .is_some()
    }
}

impl<T> Default for TaskCompletionSource<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> fmt::Debug for TaskCompletionSource<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter
            .debug_struct("TaskCompletionSource")
            .field("completed", &self.is_completed())
            .finish_non_exhaustive()
    }
}

/// Future associated with a [`TaskCompletionSource`].
pub struct TaskCompletionFuture<T> {
    state: Arc<TaskCompletionState<T>>,
    waiter_id: Option<u64>,
}

impl<T: Clone> Future for TaskCompletionFuture<T> {
    type Output = Result<T, crate::Error>;

    fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
        if let Some(result) = self
            .state
            .result
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .clone()
        {
            return Poll::Ready(result);
        }
        let id = self.waiter_id.unwrap_or_else(|| {
            let id = self.state.next_id.fetch_add(1, Ordering::Relaxed);
            self.waiter_id = Some(id);
            id
        });
        self.state
            .waiters
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .insert(id, context.waker().clone());
        let ready = self
            .state
            .result
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .clone();
        if let Some(result) = ready {
            self.state
                .waiters
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id);
            self.waiter_id = None;
            Poll::Ready(result)
        } else {
            Poll::Pending
        }
    }
}

impl<T> Drop for TaskCompletionFuture<T> {
    fn drop(&mut self) {
        if let Some(id) = self.waiter_id {
            self.state
                .waiters
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .remove(&id);
        }
    }
}

/// Cloneable clock boundary used by runtime-neutral client code.
#[derive(Clone)]
pub struct TimeProvider(Arc<dyn Fn() -> std::time::SystemTime + Send + Sync>);

impl TimeProvider {
    /// Returns the process system clock.
    #[must_use]
    pub fn system() -> Self {
        Self(Arc::new(std::time::SystemTime::now))
    }

    /// Creates an injected clock for deterministic tests and embedders.
    #[must_use]
    pub fn from_fn<F>(clock: F) -> Self
    where
        F: Fn() -> std::time::SystemTime + Send + Sync + 'static,
    {
        Self(Arc::new(clock))
    }

    #[must_use]
    pub fn get_utc_now(&self) -> std::time::SystemTime {
        (self.0)()
    }
}

impl Default for TimeProvider {
    fn default() -> Self {
        Self::system()
    }
}

impl fmt::Debug for TimeProvider {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("TimeProvider(<injected clock>)")
    }
}

pub struct MediaTypeHeaderValue(pub String);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpRequest {
    pub method: String,
    pub uri: Uri,
    pub headers: BTreeMap<String, String>,
    pub content_type: Option<String>,
    pub body: Vec<u8>,
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct HttpResponse {
    pub status_code: u16,
    pub headers: BTreeMap<String, String>,
    pub content_type: Option<String>,
    pub body: Vec<u8>,
}

impl HttpResponse {
    #[must_use]
    pub const fn is_success_status_code(&self) -> bool {
        self.status_code >= 200 && self.status_code < 300
    }
}

pub type HttpResponseFuture = Pin<Box<dyn Future<Output = HttpResponse> + Send>>;

type HttpHandler = dyn Fn(HttpRequest, CancellationToken) -> HttpResponseFuture + Send + Sync;

#[derive(Clone)]
pub struct HttpMessageHandler(Arc<HttpHandler>);

impl HttpMessageHandler {
    pub fn new<F, Fut>(handler: F) -> Self
    where
        F: Fn(HttpRequest, CancellationToken) -> Fut + Send + Sync + 'static,
        Fut: Future<Output = HttpResponse> + Send + 'static,
    {
        Self(Arc::new(move |request, cancellation_token| {
            Box::pin(handler(request, cancellation_token))
        }))
    }

    #[must_use]
    pub fn send(
        &self,
        request: HttpRequest,
        cancellation_token: CancellationToken,
    ) -> HttpResponseFuture {
        (self.0)(request, cancellation_token)
    }
}

pub struct HttpClient;

pub struct HttpMethod(pub String);

pub struct AuthenticationHeaderValue(pub String);

/// Executor-neutral progress sink used by mapped upload/download APIs.
pub trait IProgress<T>: Send + Sync {
    fn report(&self, value: T);
}

impl<T, F> IProgress<T> for F
where
    F: Fn(T) + Send + Sync,
{
    fn report(&self, value: T) {
        self(value);
    }
}

pub struct IEnumerator;

pub struct WaitHandle;

#[derive(Clone, Debug)]
pub struct FrozenDictionary<TKey, TValue>(pub std::collections::HashMap<TKey, TValue>);

#[derive(Clone, Debug)]
pub struct IDictionary<TKey, TValue>(pub std::collections::HashMap<TKey, TValue>);

#[derive(Clone, Debug)]
pub struct SortedList<TKey, TValue>(pub std::collections::BTreeMap<TKey, TValue>);

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Matrix4x4(pub [f32; 16]);

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Quaternion(pub [f32; 4]);

#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Vector3(pub [f32; 3]);

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct StringWriter(pub String);

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct TypeId(pub &'static str);

pub struct Span<T>(pub PhantomData<fn(T)>);

pub struct RandomSource;

struct AsyncEnumerableState<T> {
    values: std::collections::VecDeque<T>,
    closed: bool,
    waiters: Vec<Waker>,
    cancellation: Option<CancellationToken>,
}

/// A cloneable, producer-driven equivalent of `IAsyncEnumerable<T>`.
///
/// Native managers keep a producer clone and publish correlated protocol
/// results. Consumers call [`IAsyncEnumerable::next`] until it returns `None`.
pub struct IAsyncEnumerable<T>(Arc<Mutex<AsyncEnumerableState<T>>>);

impl<T> Clone for IAsyncEnumerable<T> {
    fn clone(&self) -> Self {
        Self(Arc::clone(&self.0))
    }
}

impl<T> Default for IAsyncEnumerable<T> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T> IAsyncEnumerable<T> {
    #[must_use]
    pub fn new() -> Self {
        Self(Arc::new(Mutex::new(AsyncEnumerableState {
            values: std::collections::VecDeque::new(),
            closed: false,
            waiters: Vec::new(),
            cancellation: None,
        })))
    }

    #[must_use]
    pub fn with_cancellation(cancellation: CancellationToken) -> Self {
        let value = Self::new();
        value
            .0
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .cancellation = Some(cancellation);
        value
    }

    /// Publishes one item and wakes pending consumers.
    pub fn push(&self, value: T) {
        let waiters = {
            let mut state = self
                .0
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner);
            if state
                .cancellation
                .as_ref()
                .is_some_and(CancellationToken::is_cancellation_requested)
            {
                state.closed = true;
            }
            if state.closed {
                return;
            }
            state.values.push_back(value);
            std::mem::take(&mut state.waiters)
        };
        for waiter in waiters {
            waiter.wake();
        }
    }

    /// Completes the sequence after already queued items are consumed.
    pub fn close(&self) {
        let waiters = {
            let mut state = self
                .0
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner);
            state.closed = true;
            std::mem::take(&mut state.waiters)
        };
        for waiter in waiters {
            waiter.wake();
        }
    }

    #[must_use]
    pub fn next(&self) -> AsyncEnumerableNext<T> {
        let cancellation = self
            .0
            .lock()
            .unwrap_or_else(std::sync::PoisonError::into_inner)
            .cancellation
            .clone()
            .map(|token| token.cancelled());
        AsyncEnumerableNext {
            state: Arc::clone(&self.0),
            registered: false,
            cancellation,
        }
    }
}

pub struct AsyncEnumerableNext<T> {
    state: Arc<Mutex<AsyncEnumerableState<T>>>,
    registered: bool,
    cancellation: Option<CancellationFuture>,
}

impl<T> Future for AsyncEnumerableNext<T> {
    type Output = Option<T>;

    fn poll(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Self::Output> {
        let should_register = !self.registered;
        if let Some(cancelled) = self.cancellation.as_mut()
            && Pin::new(cancelled).poll(context).is_ready()
        {
            self.state
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner)
                .closed = true;
        }
        let outcome = {
            let mut state = self
                .state
                .lock()
                .unwrap_or_else(std::sync::PoisonError::into_inner);
            if let Some(value) = state.values.pop_front() {
                Some(Poll::Ready(Some(value)))
            } else if state.closed {
                Some(Poll::Ready(None))
            } else {
                if should_register {
                    state.waiters.push(context.waker().clone());
                }
                None
            }
        };
        if let Some(outcome) = outcome {
            outcome
        } else {
            self.registered = true;
            Poll::Pending
        }
    }
}

/// Read-only, cheaply clonable hash-map snapshot corresponding to
/// `System.Collections.Immutable.ImmutableDictionary<TKey, TValue>`.
#[derive(Clone, Debug)]
pub struct ImmutableDictionary<TKey, TValue>(Arc<std::collections::HashMap<TKey, TValue>>);

impl<TKey, TValue> PartialEq for ImmutableDictionary<TKey, TValue>
where
    TKey: Eq + std::hash::Hash,
    TValue: PartialEq,
{
    fn eq(&self, other: &Self) -> bool {
        self.0 == other.0
    }
}

impl<TKey, TValue> Eq for ImmutableDictionary<TKey, TValue>
where
    TKey: Eq + std::hash::Hash,
    TValue: Eq,
{
}

impl<TKey, TValue> ImmutableDictionary<TKey, TValue> {
    /// Creates an immutable snapshot from an owned map.
    #[must_use]
    pub fn from_map(values: std::collections::HashMap<TKey, TValue>) -> Self {
        Self(Arc::new(values))
    }

    /// Returns the number of entries in the snapshot.
    #[must_use]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns whether the snapshot contains no entries.
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Iterates over keys and values in the snapshot.
    #[must_use]
    pub fn iter(&self) -> std::collections::hash_map::Iter<'_, TKey, TValue> {
        self.0.iter()
    }

    /// Iterates over values in the snapshot.
    #[must_use]
    pub fn values(&self) -> std::collections::hash_map::Values<'_, TKey, TValue> {
        self.0.values()
    }

    /// Looks up a value by borrowed key.
    #[must_use]
    pub fn get<Q>(&self, key: &Q) -> Option<&TValue>
    where
        TKey: std::borrow::Borrow<Q> + Eq + std::hash::Hash,
        Q: Eq + std::hash::Hash + ?Sized,
    {
        self.0.get(key)
    }
}

impl<TKey, TValue> Default for ImmutableDictionary<TKey, TValue> {
    fn default() -> Self {
        Self(Arc::new(std::collections::HashMap::new()))
    }
}

impl<TKey, TValue> From<std::collections::HashMap<TKey, TValue>>
    for ImmutableDictionary<TKey, TValue>
{
    fn from(values: std::collections::HashMap<TKey, TValue>) -> Self {
        Self::from_map(values)
    }
}

impl<TKey, TValue> std::ops::Deref for ImmutableDictionary<TKey, TValue> {
    type Target = std::collections::HashMap<TKey, TValue>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'a, TKey, TValue> IntoIterator for &'a ImmutableDictionary<TKey, TValue> {
    type Item = (&'a TKey, &'a TValue);
    type IntoIter = std::collections::hash_map::Iter<'a, TKey, TValue>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

/// Read-only, cheaply clonable snapshot corresponding to
/// `System.Collections.Immutable.ImmutableList<T>`.
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
pub struct ImmutableList<T>(Arc<[T]>);

impl<T> ImmutableList<T> {
    /// Creates an immutable snapshot from owned values.
    #[must_use]
    pub fn from_vec(values: Vec<T>) -> Self {
        Self(values.into())
    }

    /// Returns the snapshot as a slice.
    #[must_use]
    pub fn as_slice(&self) -> &[T] {
        &self.0
    }

    /// Returns the number of values in the snapshot.
    #[must_use]
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns whether the snapshot contains no values.
    #[must_use]
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// Iterates over the snapshot.
    pub fn iter(&self) -> std::slice::Iter<'_, T> {
        self.0.iter()
    }
}

impl<T> From<Vec<T>> for ImmutableList<T> {
    fn from(values: Vec<T>) -> Self {
        Self::from_vec(values)
    }
}

impl<T> std::ops::Deref for ImmutableList<T> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        self.as_slice()
    }
}

impl<'a, T> IntoIterator for &'a ImmutableList<T> {
    type Item = &'a T;
    type IntoIter = std::slice::Iter<'a, T>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

pub struct ICollection;

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct UnicodeCategory(pub i32);

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct TextEncoding;

pub struct SocketException;

#[cfg(test)]
mod tests {
    use super::{
        CancellationToken, CancellationTokenSource, HttpMessageHandler, HttpRequest, HttpResponse,
        Object, TimeProvider, Uri,
    };
    use std::collections::BTreeMap;
    use std::future::Future;
    use std::sync::Arc;
    use std::task::{Context, Poll, Waker};
    use std::time::{Duration, SystemTime};

    #[test]
    fn cancellation_wakes_waiters_and_propagates_from_linked_tokens() {
        let parent = CancellationTokenSource::new();
        let linked = CancellationTokenSource::new_linked(&[parent.token()]);
        let mut future = Box::pin(linked.token().cancelled());
        let mut context = Context::from_waker(Waker::noop());
        assert!(matches!(future.as_mut().poll(&mut context), Poll::Pending));

        parent.cancel();
        assert!(linked.token().is_cancellation_requested());
        assert!(matches!(
            future.as_mut().poll(&mut context),
            Poll::Ready(())
        ));
        assert_eq!(
            linked.token().throw_if_cancellation_requested(),
            Err(crate::Error::Cancelled)
        );
        parent.cancel();
    }

    #[test]
    fn injected_time_provider_is_deterministic_and_redacted() {
        let instant = SystemTime::UNIX_EPOCH + Duration::from_secs(42);
        let provider = TimeProvider::from_fn(move || instant);
        assert_eq!(provider.get_utc_now(), instant);
        assert!(!format!("{provider:?}").contains("42"));
    }

    #[test]
    fn http_handler_preserves_request_and_response_data() {
        let handler = HttpMessageHandler::new(|request, _cancellation_token| async move {
            HttpResponse {
                status_code: 201,
                headers: request.headers,
                content_type: request.content_type,
                body: request.body,
            }
        });
        let mut response = handler.send(
            HttpRequest {
                method: "PUT".into(),
                uri: Uri("http://example.test/".into()),
                headers: BTreeMap::from([("Location".into(), "slcaps://fixture".into())]),
                content_type: Some("application/llsd+xml".into()),
                body: b"test".to_vec(),
            },
            CancellationToken::default(),
        );
        let mut context = Context::from_waker(Waker::noop());
        let response = match Future::poll(response.as_mut(), &mut context) {
            Poll::Ready(response) => response,
            Poll::Pending => panic!("immediate handler unexpectedly remained pending"),
        };

        assert!(response.is_success_status_code());
        assert_eq!(response.headers["Location"], "slcaps://fixture");
        assert_eq!(
            response.content_type.as_deref(),
            Some("application/llsd+xml")
        );
        assert_eq!(response.body, b"test");
        assert!(
            !HttpResponse {
                status_code: 399,
                headers: BTreeMap::new(),
                content_type: None,
                body: Vec::new(),
            }
            .is_success_status_code()
        );
    }

    #[test]
    fn opaque_objects_downcast_and_preserve_reference_identity() {
        let object = Object::opaque(String::from("managed image boundary"));
        assert_eq!(
            object.downcast_ref::<String>().map(String::as_str),
            Some("managed image boundary")
        );
        assert!(object.downcast_ref::<Vec<u8>>().is_none());
        let first = object.downcast_arc::<String>().expect("shared string");
        let second = object.downcast_arc::<String>().expect("shared string");
        assert!(Arc::ptr_eq(&first, &second));
        assert_eq!(object, object.clone());
        assert_ne!(
            object,
            Object::opaque(String::from("managed image boundary"))
        );
    }
}
