1use std::collections::HashMap;
2use std::sync::{Arc, Mutex};
3
4use serde_json::Value;
5
6use crate::events::EventEmitter;
7
8pub struct GlobalContext {
30 module_states: Mutex<HashMap<String, Value>>,
32
33 events: EventEmitter,
35
36 router: Mutex<Option<Arc<crate::router::HypenRouter>>>,
38}
39
40impl GlobalContext {
41 pub fn new() -> Self {
42 Self {
43 module_states: Mutex::new(HashMap::new()),
44 events: EventEmitter::new(),
45 router: Mutex::new(None),
46 }
47 }
48
49 pub fn register_module_state(&self, name: impl Into<String>, state: Value) {
53 self.module_states
54 .lock()
55 .unwrap()
56 .insert(name.into(), state);
57 }
58
59 pub fn get_module_state(&self, name: &str) -> Option<Value> {
61 self.module_states.lock().unwrap().get(name).cloned()
62 }
63
64 pub fn has_module(&self, name: &str) -> bool {
66 self.module_states.lock().unwrap().contains_key(name)
67 }
68
69 pub fn module_names(&self) -> Vec<String> {
71 self.module_states.lock().unwrap().keys().cloned().collect()
72 }
73
74 pub fn unregister_module(&self, name: &str) {
76 self.module_states.lock().unwrap().remove(name);
77 }
78
79 pub fn global_state(&self) -> Value {
81 let states = self.module_states.lock().unwrap();
82 let mut map = serde_json::Map::new();
83 for (name, state) in states.iter() {
84 map.insert(name.clone(), state.clone());
85 }
86 Value::Object(map)
87 }
88
89 pub fn events(&self) -> &EventEmitter {
93 &self.events
94 }
95
96 pub fn set_router(&self, router: Arc<crate::router::HypenRouter>) {
100 *self.router.lock().unwrap() = Some(router);
101 }
102
103 pub fn router(&self) -> Option<Arc<crate::router::HypenRouter>> {
105 self.router.lock().unwrap().clone()
106 }
107}
108
109impl Default for GlobalContext {
110 fn default() -> Self {
111 Self::new()
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118 use serde_json::json;
119
120 #[test]
121 fn test_register_and_get_state() {
122 let ctx = GlobalContext::new();
123 ctx.register_module_state("counter", json!({"count": 5}));
124
125 let state = ctx.get_module_state("counter").unwrap();
126 assert_eq!(state["count"], 5);
127 }
128
129 #[test]
130 fn test_module_names() {
131 let ctx = GlobalContext::new();
132 ctx.register_module_state("a", json!({}));
133 ctx.register_module_state("b", json!({}));
134
135 let mut names = ctx.module_names();
136 names.sort();
137 assert_eq!(names, vec!["a", "b"]);
138 }
139
140 #[test]
141 fn test_unregister() {
142 let ctx = GlobalContext::new();
143 ctx.register_module_state("test", json!({}));
144 assert!(ctx.has_module("test"));
145
146 ctx.unregister_module("test");
147 assert!(!ctx.has_module("test"));
148 }
149
150 #[test]
151 fn test_global_state() {
152 let ctx = GlobalContext::new();
153 ctx.register_module_state("counter", json!({"count": 1}));
154 ctx.register_module_state("user", json!({"name": "Alice"}));
155
156 let global = ctx.global_state();
157 assert_eq!(global["counter"]["count"], 1);
158 assert_eq!(global["user"]["name"], "Alice");
159 }
160
161 #[test]
162 fn test_events_integration() {
163 use std::sync::atomic::{AtomicI32, Ordering};
164
165 let ctx = GlobalContext::new();
166 let count = Arc::new(AtomicI32::new(0));
167 let count_clone = count.clone();
168
169 ctx.events().on("test", move |_| {
170 count_clone.fetch_add(1, Ordering::SeqCst);
171 });
172
173 ctx.events().emit("test", &json!(null));
174 assert_eq!(count.load(Ordering::SeqCst), 1);
175 }
176}