1use std::{
7 collections::HashMap,
8 sync::{Arc, Mutex, RwLock},
9};
10
11use crate::{
12 component::{
13 update_scheduler::{UpdatePriority, UpdateScheduler},
14 AnyComponent, ComponentId, LifecyclePhase,
15 },
16 events::EventEmitter,
17 state::{ReactiveScope, StateContainer},
18};
19
20type LifecycleHook = Box<dyn FnMut(&mut dyn AnyComponent) + Send + Sync>;
22type LifecycleHooks = HashMap<LifecyclePhase, Vec<LifecycleHook>>;
23
24#[derive(Clone)]
26pub struct Context {
27 state: StateContainer,
29
30 reactive_scope: Arc<ReactiveScope>,
32
33 events: EventEmitter,
35
36 update_scheduler: UpdateScheduler,
38
39 lifecycle_hooks: Arc<Mutex<LifecycleHooks>>,
41
42 lifecycle_phase: Arc<RwLock<LifecyclePhase>>,
44
45 component_id: Option<ComponentId>,
47}
48
49impl Default for Context {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl Context {
56 pub fn new() -> Self {
58 Self {
59 state: StateContainer::new(),
60 reactive_scope: Arc::new(ReactiveScope::new()),
61 events: EventEmitter::new(),
62 update_scheduler: UpdateScheduler::new(),
63 lifecycle_hooks: Arc::new(Mutex::new(HashMap::new())),
64 lifecycle_phase: Arc::new(RwLock::new(LifecyclePhase::Created)),
65 component_id: None,
66 }
67 }
68
69 pub fn for_component(component_id: ComponentId) -> Self {
71 let mut context = Self::new();
72 context.component_id = Some(component_id);
73 context
74 }
75
76 pub fn state(&self) -> &StateContainer {
78 &self.state
79 }
80
81 pub fn state_mut(&mut self) -> &mut StateContainer {
83 &mut self.state
84 }
85
86 pub fn reactive_scope(&self) -> &Arc<ReactiveScope> {
88 &self.reactive_scope
89 }
90
91 pub fn events(&self) -> &EventEmitter {
93 &self.events
94 }
95
96 pub fn events_mut(&mut self) -> &mut EventEmitter {
98 &mut self.events
99 }
100
101 pub fn update_scheduler(&self) -> &UpdateScheduler {
103 &self.update_scheduler
104 }
105
106 pub fn lifecycle_phase(&self) -> LifecyclePhase {
108 self.lifecycle_phase
109 .read()
110 .map(|phase| *phase)
111 .unwrap_or_else(|_| {
112 eprintln!("Error reading lifecycle phase, defaulting to Created");
115 LifecyclePhase::Created
116 })
117 }
118
119 pub fn set_lifecycle_phase(&self, phase: LifecyclePhase) {
121 if let Ok(mut current_phase) = self.lifecycle_phase.write() {
122 *current_phase = phase;
123 }
124 }
125
126 pub fn register_lifecycle_hook<F>(&self, phase: LifecyclePhase, hook: F)
128 where
129 F: FnMut(&mut dyn AnyComponent) + Send + Sync + 'static,
130 {
131 if let Ok(mut hooks) = self.lifecycle_hooks.lock() {
132 hooks
133 .entry(phase)
134 .or_insert_with(Vec::new)
135 .push(Box::new(hook));
136 }
137 }
138
139 pub fn execute_lifecycle_hooks(&self, phase: LifecyclePhase, component: &mut dyn AnyComponent) {
141 if let Ok(mut hooks) = self.lifecycle_hooks.lock() {
142 if let Some(phase_hooks) = hooks.get_mut(&phase) {
143 for hook in phase_hooks.iter_mut() {
144 hook(component);
145 }
146 }
147 }
148 }
149
150 pub fn request_update(&self, component_id: ComponentId) -> Result<(), String> {
152 self.update_scheduler
153 .schedule_update(component_id, UpdatePriority::Normal)
154 }
155
156 pub fn request_critical_update(&self, component_id: ComponentId) -> Result<(), String> {
158 self.update_scheduler
159 .schedule_update(component_id, UpdatePriority::Critical)
160 }
161
162 pub fn process_updates<F>(&self, update_fn: F) -> Result<usize, String>
164 where
165 F: FnMut(ComponentId) -> Result<(), String>,
166 {
167 self.update_scheduler.process_updates(update_fn)
168 }
169
170 pub fn component_id(&self) -> Option<ComponentId> {
172 self.component_id
173 }
174
175 pub fn set_component_id(&mut self, id: ComponentId) {
177 self.component_id = Some(id);
178 }
179
180 pub fn create_child_context(&self, child_id: ComponentId) -> Self {
182 let mut child = self.clone();
183 child.set_component_id(child_id);
184 child
185 }
186}
187
188impl std::fmt::Debug for Context {
189 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190 f.debug_struct("Context")
191 .field("state", &self.state)
192 .field("reactive_scope", &self.reactive_scope)
193 .field("events", &self.events)
194 .field("update_scheduler", &self.update_scheduler)
195 .field(
196 "lifecycle_hooks",
197 &format!(
198 "<{} hooks>",
199 self.lifecycle_hooks
200 .lock()
201 .map(|hooks| hooks.len())
202 .unwrap_or(0)
203 ),
204 )
205 .field("lifecycle_phase", &self.lifecycle_phase)
206 .field("component_id", &self.component_id)
207 .finish()
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214 use crate::component::{ComponentError, ComponentId, LifecyclePhase, Props};
215
216 struct TestComponent {
218 id: ComponentId,
219 context: Context,
220 lifecycle_events: Vec<String>,
221 phase: LifecyclePhase,
222 }
223
224 impl TestComponent {
225 fn new(context: Context) -> Self {
226 let id = ComponentId::new();
227 Self {
228 id,
229 context,
230 lifecycle_events: Vec::new(),
231 phase: LifecyclePhase::Created,
232 }
233 }
234 }
235
236 impl AnyComponent for TestComponent {
237 fn component_id(&self) -> ComponentId {
238 self.id
239 }
240
241 fn lifecycle_phase(&self) -> LifecyclePhase {
242 self.phase
243 }
244
245 fn set_lifecycle_phase(&mut self, phase: LifecyclePhase) {
246 self.phase = phase;
247 }
248
249 fn request_update(&mut self) -> Result<(), ComponentError> {
250 self.context
251 .request_update(self.id)
252 .map_err(|e| ComponentError::UpdateError(e))
253 }
254
255 fn as_any(&self) -> &dyn std::any::Any {
256 self
257 }
258
259 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
260 self
261 }
262
263 fn type_name(&self) -> &'static str {
264 "TestComponent"
265 }
266
267 fn any_initialize(&mut self) -> Result<(), ComponentError> {
268 self.lifecycle_events.push("initialize".to_string());
269 Ok(())
270 }
271
272 fn any_mount(&mut self) -> Result<(), ComponentError> {
273 self.lifecycle_events.push("mount".to_string());
274 Ok(())
275 }
276
277 fn any_before_update(&mut self, _props: Box<dyn Props>) -> Result<(), ComponentError> {
278 self.lifecycle_events.push("before_update".to_string());
279 Ok(())
280 }
281
282 fn any_update(&mut self, _props: Box<dyn Props>) -> Result<(), ComponentError> {
283 self.lifecycle_events.push("update".to_string());
284 Ok(())
285 }
286
287 fn any_after_update(&mut self) -> Result<(), ComponentError> {
288 self.lifecycle_events.push("after_update".to_string());
289 Ok(())
290 }
291
292 fn any_before_unmount(&mut self) -> Result<(), ComponentError> {
293 self.lifecycle_events.push("before_unmount".to_string());
294 Ok(())
295 }
296
297 fn any_unmount(&mut self) -> Result<(), ComponentError> {
298 self.lifecycle_events.push("unmount".to_string());
299 Ok(())
300 }
301
302 fn any_on_mount(
303 &mut self,
304 _context: &crate::component::MountContext,
305 ) -> Result<(), ComponentError> {
306 self.lifecycle_events.push("on_mount".to_string());
307 Ok(())
308 }
309
310 fn any_before_mount(&mut self) -> Result<(), ComponentError> {
311 self.lifecycle_events.push("before_mount".to_string());
312 Ok(())
313 }
314
315 fn any_after_mount(&mut self) -> Result<(), ComponentError> {
316 self.lifecycle_events.push("after_mount".to_string());
317 Ok(())
318 }
319
320 fn any_on_update(
321 &mut self,
322 _changes: &crate::component::state_tracking::StateChanges,
323 ) -> Result<(), ComponentError> {
324 self.lifecycle_events.push("on_update".to_string());
325 Ok(())
326 }
327
328 fn any_on_unmount(
329 &mut self,
330 _context: &crate::component::UnmountContext,
331 ) -> Result<(), ComponentError> {
332 self.lifecycle_events.push("on_unmount".to_string());
333 Ok(())
334 }
335
336 fn any_after_unmount(&mut self) -> Result<(), ComponentError> {
337 self.lifecycle_events.push("after_unmount".to_string());
338 Ok(())
339 }
340 }
341
342 #[test]
343 fn test_context_lifecycle_hooks() {
344 let context = Context::new();
346
347 context.register_lifecycle_hook(LifecyclePhase::Mounting, |component| {
349 let any = component.as_any_mut();
350 if let Some(test_component) = any.downcast_mut::<TestComponent>() {
351 test_component
352 .lifecycle_events
353 .push("mounting_hook".to_string());
354 }
355 });
356
357 context.register_lifecycle_hook(LifecyclePhase::Unmounting, |component| {
358 let any = component.as_any_mut();
359 if let Some(test_component) = any.downcast_mut::<TestComponent>() {
360 test_component
361 .lifecycle_events
362 .push("unmounting_hook".to_string());
363 }
364 });
365
366 let mut component = TestComponent::new(context.clone());
368
369 context.execute_lifecycle_hooks(LifecyclePhase::Mounting, &mut component);
371
372 assert!(component
374 .lifecycle_events
375 .contains(&"mounting_hook".to_string()));
376
377 context.execute_lifecycle_hooks(LifecyclePhase::Unmounting, &mut component);
379
380 assert!(component
382 .lifecycle_events
383 .contains(&"unmounting_hook".to_string()));
384 }
385
386 #[test]
387 fn test_context_update_scheduling() {
388 let context = Context::new();
390
391 let c1 = ComponentId::new();
393 let c2 = ComponentId::new();
394
395 context.request_update(c1).unwrap();
397 context.request_critical_update(c2).unwrap();
398
399 let mut processed = Vec::new();
401 let updated = context
402 .process_updates(|id| {
403 processed.push(id);
404 Ok(())
405 })
406 .unwrap();
407
408 assert_eq!(updated, 2);
410 assert_eq!(processed.len(), 2);
411
412 assert_eq!(processed[0], c2);
414 assert_eq!(processed[1], c1);
415 }
416
417 #[test]
418 fn test_child_context() {
419 let parent_context = Context::new();
421 let parent_id = ComponentId::new();
422
423 let child_id = ComponentId::new();
425 let child_context = parent_context.create_child_context(child_id);
426
427 assert_eq!(child_context.component_id(), Some(child_id));
429
430 parent_context.request_update(parent_id).unwrap();
432
433 assert!(parent_context
435 .update_scheduler
436 .has_pending_updates()
437 .unwrap());
438 assert!(child_context
439 .update_scheduler
440 .has_pending_updates()
441 .unwrap());
442 }
443}