use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::time::Duration;
use js_sys::Array;
use crate::reactive::{EffectId, ScopeId, SignalId};
type EffectRunHook = Rc<dyn Fn(EffectId, Option<ScopeId>, Duration)>;
type HandlerInvokeHook = Rc<dyn Fn(ScopeId, &str, &Array, Duration)>;
type QueueChangeHook = Rc<dyn Fn(&[EffectId])>;
type SignalTriggerHook = Rc<dyn Fn(SignalId)>;
type RouteChangeHook = Rc<dyn Fn(&str, &HashMap<String, String>)>;
#[derive(Default)]
pub(crate) struct Hooks {
pub on_effect_run: Option<EffectRunHook>,
pub on_handler_invoke: Option<HandlerInvokeHook>,
pub on_queue_change: Option<QueueChangeHook>,
pub on_signal_trigger: Option<SignalTriggerHook>,
pub on_route_change: Option<RouteChangeHook>,
}
thread_local! {
pub(crate) static HOOKS: RefCell<Hooks> = RefCell::new(Hooks::default());
}
pub fn set_on_effect_run(f: EffectRunHook) {
HOOKS.with(|h| h.borrow_mut().on_effect_run = Some(f));
}
pub fn set_on_handler_invoke(f: HandlerInvokeHook) {
HOOKS.with(|h| h.borrow_mut().on_handler_invoke = Some(f));
}
pub fn set_on_queue_change(f: QueueChangeHook) {
HOOKS.with(|h| h.borrow_mut().on_queue_change = Some(f));
}
pub fn set_on_signal_trigger(f: SignalTriggerHook) {
HOOKS.with(|h| h.borrow_mut().on_signal_trigger = Some(f));
}
pub fn set_on_route_change(f: RouteChangeHook) {
HOOKS.with(|h| h.borrow_mut().on_route_change = Some(f));
}
#[doc(hidden)]
pub fn _reset() {
HOOKS.with(|h| *h.borrow_mut() = Hooks::default());
}
pub(crate) fn fire_effect_run(id: EffectId, scope: Option<ScopeId>, duration: Duration) {
let hook = HOOKS.with(|h| h.borrow().on_effect_run.clone());
if let Some(f) = hook {
f(id, scope, duration);
}
}
pub(crate) fn fire_handler_invoke(scope: ScopeId, name: &str, args: &Array, duration: Duration) {
let hook = HOOKS.with(|h| h.borrow().on_handler_invoke.clone());
if let Some(f) = hook {
f(scope, name, args, duration);
}
}
pub(crate) fn fire_queue_change(added: &[EffectId]) {
let hook = HOOKS.with(|h| h.borrow().on_queue_change.clone());
if let Some(f) = hook {
f(added);
}
}
pub(crate) fn fire_signal_trigger(id: SignalId) {
let hook = HOOKS.with(|h| h.borrow().on_signal_trigger.clone());
if let Some(f) = hook {
f(id);
}
}
pub(crate) fn fire_route_change(path: &str, params: &HashMap<String, String>) {
let hook = HOOKS.with(|h| h.borrow().on_route_change.clone());
if let Some(f) = hook {
f(path, params);
}
}