use std::cell::RefCell;

use parking_lot::ReentrantMutex;

use crate::{Interface, Main, Resource};

mod client;
mod display;
mod globals;
mod resource;

pub(crate) use self::client::ClientInner;
pub(crate) use self::display::DisplayInner;
pub(crate) use self::globals::GlobalInner;
pub(crate) use self::resource::ResourceInner;

lazy_static::lazy_static! {
    // This lock *must* be held whenever an ffi call is made to
    // the C lib, as it is not Sync.
    pub(crate) static ref C_SAFETY: ReentrantMutex<()> = ReentrantMutex::new(());
}

/// A handle to the object map internal to the library state
///
/// This type is only used by code generated by `wayland-scanner`, and can not
/// be instantiated directly.
#[derive(Debug)]
pub enum ResourceMap {}

impl ResourceMap {
    /// Returns the `Resource` corresponding to a given id
    pub fn get<I: Interface>(&mut self, _id: u32) -> Option<Resource<I>> {
        match *self {}
    }
    /// Creates a `NewResource` for a given id
    pub fn get_new<I: Interface + AsRef<Resource<I>> + From<Resource<I>>>(
        &mut self,
        _id: u32,
    ) -> Option<Main<I>> {
        match *self {}
    }
}

scoped_tls::scoped_thread_local! {
    pub(crate) static DISPATCH_DATA: RefCell<crate::DispatchData>
}

fn with_dispatch_data<T, F>(data: crate::DispatchData, f: F) -> T
where
    F: FnOnce() -> T,
{
    // We erase the lifetime of the callback to be able to store it in the tls,
    // it's safe as it'll only last until the end of this function call anyway
    let data = unsafe { std::mem::transmute(data) };
    DISPATCH_DATA.set(&RefCell::new(data), f)
}
