1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::{
    any::{Any, TypeId},
    collections::HashMap,
};

use crate::events::matrix_event::MatrixEventSender;

use super::storage::{Storage, StorageReadGuard, StorageWriteGuard};

pub trait Resource {}

pub struct ResourceHolder<T: Resource> {
    data: Option<T>,
}

impl<T: Resource + 'static> ResourceHolder<T> {
    pub fn new_empty() -> Self {
        ResourceHolder { data: None }
    }
    pub fn new(data: T) -> Self {
        ResourceHolder { data: Some(data) }
    }

    pub fn get_or_default(&mut self) -> &mut T
    where
        T: Default,
    {
        self.data.get_or_insert_with(Default::default)
    }
    pub fn get_mut(&mut self) -> Option<&mut T> {
        match &mut self.data {
            Some(data) => Some(data),
            None => None,
        }
    }
    pub fn get(&self) -> Option<&T> {
        match &self.data {
            Some(data) => Some(data),
            None => None,
        }
    }
    pub(crate) fn get_or_insert(&mut self, data: T) -> &mut T {
        self.data.get_or_insert(data)
    }
    pub(crate) fn get_or_insert_with(&mut self, data: impl FnOnce() -> T) -> &mut T {
        self.data.get_or_insert_with(data)
    }
    pub(crate) fn clear(&mut self) {
        self.data.take();
    }
}

pub struct ResourceRegistry {
    data: HashMap<TypeId, Box<dyn Any>>,
    event_handler: MatrixEventSender,
}

impl ResourceRegistry {
    pub fn empty(event_handler: MatrixEventSender) -> Self {
        Self {
            data: Default::default(),
            event_handler,
        }
    }

    pub fn get_mut<T: Resource + 'static>(
        &mut self,
    ) -> Option<StorageWriteGuard<ResourceHolder<T>>> {
        self.data
            .entry(TypeId::of::<T>())
            .or_insert(Box::new(Storage::new(ResourceHolder::<T>::new_empty())))
            .downcast_mut::<Storage<ResourceHolder<T>>>()
            .expect("this value should be of this type")
            .write()
    }

    pub fn get<T: Resource + 'static>(&mut self) -> Option<StorageReadGuard<ResourceHolder<T>>> {
        self.data
            .entry(TypeId::of::<T>())
            .or_insert(Box::new(Storage::new(ResourceHolder::<T>::new_empty())))
            .downcast_ref::<Storage<ResourceHolder<T>>>()
            .expect("this value should be of this type")
            .read()
    }
    pub fn insert<T: Resource + 'static>(&mut self, resource: T) {
        self.data
            .insert(TypeId::of::<T>(), Box::new(ResourceHolder::new(resource)));
    }
}

mod tests {

    #[test]
    fn test() {}
}