use web_sys::Element;
use std::cell::RefCell;
use std::collections::HashMap;
use crate::dom::lifecycle;
use super::ownership;
use super::lifecycle as lc;
thread_local! {
static TIMER_HANDLES: RefCell<HashMap<String, Vec<i32>>> = RefCell::new(HashMap::new());
}
pub fn track_timer(uid: &str, handle: i32) {
if handle < 0 { return; }
TIMER_HANDLES.with(|t| {
t.borrow_mut()
.entry(uid.to_string())
.or_default()
.push(handle);
});
}
pub fn cleanup_uid(uid: &str) {
let descendants = ownership::release(uid);
for child_uid in &descendants {
if child_uid == uid { continue; }
super::listeners::cleanup(child_uid);
TIMER_HANDLES.with(|t| {
if let Some(handles) = t.borrow_mut().remove(child_uid) {
for h in handles { super::timers::cancel_timeout(h); }
}
});
lc::set_state(child_uid, lc::LifecycleState::Destroy);
lc::remove(child_uid);
}
super::listeners::cleanup(uid);
TIMER_HANDLES.with(|t| {
if let Some(handles) = t.borrow_mut().remove(uid) {
for h in handles {
super::timers::cancel_timeout(h);
}
}
});
if let Some(doc) = web_sys::window().and_then(|w| w.document()) {
let sel = format!("[data-rs-uid=\"{}\"]", uid);
if let Ok(Some(el)) = doc.query_selector(&sel) {
lifecycle::reset(&el);
}
}
lc::set_state(uid, lc::LifecycleState::Destroy);
lc::remove(uid);
}
pub fn cleanup_subtree(root: &Element) {
use wasm_bindgen::JsCast;
if let Some(uid) = root.get_attribute("data-rs-uid") {
cleanup_uid(&uid);
}
let Ok(nodes) = root.query_selector_all("[data-rs-uid]") else { return };
for i in 0..nodes.length() {
let Some(raw) = nodes.item(i) else { continue };
let Ok(el) = raw.dyn_into::<Element>() else { continue };
if let Some(uid) = el.get_attribute("data-rs-uid") {
cleanup_uid(&uid);
}
}
}
pub fn gc() {
super::listeners::gc();
TIMER_HANDLES.with(|t| {
let Some(doc) = web_sys::window().and_then(|w| w.document()) else { return };
t.borrow_mut().retain(|uid, handles| {
let sel = format!("[data-rs-uid=\"{}\"]", uid);
let exists = doc.query_selector(&sel)
.ok().flatten()
.map(|el| el.is_connected())
.unwrap_or(false);
if !exists {
for h in handles.iter() {
super::timers::cancel_timeout(*h);
}
return false;
}
true
});
});
}