//! Internal / private prelude

#![allow(unused_imports)]

pub(crate) use ::ffi_sdk::ffi_utils::{c_slice, char_p, repr_c, NonOpaque};
pub(crate) use ::safer_ffi::prelude::Out;
pub(crate) use ::serde::{de::DeserializeOwned, Deserialize, Serialize};
pub(crate) use ::std::{
    any::Any,
    borrow::Borrow,
    collections::HashMap,
    convert::{TryFrom, TryInto},
    ops::Not,
    os::raw::c_void,
    path::{Path, PathBuf},
    pin::Pin,
    sync::Arc,
};

pub(crate) use crate::store::collection::type_traits::MutableValue;
pub(crate) mod arc {
    pub use ::std::sync::Weak;
}
pub(crate) use ::to_method::To;

pub(crate) use crate::{
    ditto::Ditto,
    error::{DittoError, ErrorKind, Result},
    prelude::*,
    store::Store,
    utils::{extension_traits::*, Str},
};

pub(crate) mod marker {
    pub(crate) use crate::utils::InvariantLifetimeMarker as InvariantLifetime;
}

pub(crate) trait IntoRustResult: Sized {
    type Ok;
    fn into_rust_result(self) -> Result<Self::Ok, ::core::num::NonZeroI32>;
    fn ok_or(self, error_kind: ErrorKind) -> Result<Self::Ok, DittoError> {
        self.into_rust_result()
            .map_err(|_| DittoError::from_ffi(error_kind))
    }
    fn ok(self) -> Result<Self::Ok, DittoError> {
        self.ok_or(ErrorKind::Internal)
    }
}

impl IntoRustResult for i32 {
    type Ok = ();

    fn into_rust_result(self: i32) -> Result<Self::Ok, ::core::num::NonZeroI32> {
        if let Some(err) = ::core::num::NonZeroI32::new(self) {
            Err(err)
        } else {
            Ok(())
        }
    }
}

impl<T> IntoRustResult for repr_c::Result_Box<T>
where
    repr_c::Box<T>: ::ffi_sdk::ffi_utils::FfiDrop,
{
    type Ok = repr_c::Box<T>;
    fn into_rust_result(self) -> Result<Self::Ok, ::core::num::NonZeroI32> {
        if let Some(err_code) = ::core::num::NonZeroI32::new(self.status_code) {
            Err(err_code)
        } else {
            Ok(self.ok_value.unwrap())
        }
    }
}

impl<T: NonOpaque> IntoRustResult for repr_c::Result_Vec<T> {
    type Ok = repr_c::Vec<T>;
    fn into_rust_result(self) -> Result<Self::Ok, ::core::num::NonZeroI32> {
        if let Some(err_code) = ::core::num::NonZeroI32::new(self.status_code) {
            Err(err_code)
        } else {
            Ok(self.c_vec.unwrap())
        }
    }
}

impl<T: NonOpaque> IntoRustResult for repr_c::Result_BoxedSlice<T> {
    type Ok = c_slice::Box<T>;
    fn into_rust_result(self) -> Result<Self::Ok, ::core::num::NonZeroI32> {
        if let Some(err_code) = ::core::num::NonZeroI32::new(self.status_code) {
            Err(err_code)
        } else {
            match self.c_slice {
                Some(slice) => Ok(slice),
                None => {
                    // FIXME : status code 0 without slice
                    Err(::core::num::NonZeroI32::new(-1).unwrap())
                }
            }
        }
    }
}

impl<T: NonOpaque> IntoRustResult for repr_c::Result<T> {
    type Ok = T;
    fn into_rust_result(self) -> Result<T, ::core::num::NonZeroI32> {
        if let Some(err_code) = ::core::num::NonZeroI32::new(self.status_code) {
            Err(err_code)
        } else {
            Ok(self.ok_value)
        }
    }
}
