use std::sync::Mutex;
use std::time::Duration;
use terrazzo::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::window;
use self::diagnostics::debug;
use self::diagnostics::warn;
use super::tick::AbortTickOnDrop;
use super::tick::Tick;
pub type Timer = XSignal<Tick>;
pub fn second_timer() -> Timer {
static TIMER: Mutex<WeakTimer> = Mutex::new(WeakTimer(XSignalWeak::new()));
create_timer(&TIMER, Duration::from_secs(1))
}
pub fn ten_seconds_timer() -> Timer {
static TIMER: Mutex<WeakTimer> = Mutex::new(WeakTimer(XSignalWeak::new()));
create_timer(&TIMER, Duration::from_secs(10))
}
pub fn fraction_timer() -> Timer {
static TIMER: Mutex<WeakTimer> = Mutex::new(WeakTimer(XSignalWeak::new()));
create_timer(&TIMER, Duration::from_millis(50))
}
pub fn minute_timer() -> Timer {
static TIMER: Mutex<WeakTimer> = Mutex::new(WeakTimer(XSignalWeak::new()));
create_timer(&TIMER, Duration::from_secs(60))
}
fn create_timer(timer: &Mutex<WeakTimer>, period: Duration) -> Timer {
let mut lock = timer.lock().unwrap();
if let Some(timer) = lock.0.upgrade() {
return timer;
}
let timer = create_timer_impl(period);
*lock = WeakTimer(timer.downgrade());
return timer;
}
fn create_timer_impl(period: Duration) -> Timer {
debug!("Create timer for period={period:?}");
let timer = Timer::new("second-timer", Tick::new(period));
let timer_weak = timer.downgrade();
let closure: Closure<dyn Fn()> = Closure::new(move || {
let Some(timer) = timer_weak.upgrade() else {
warn!("MISSING TIMER");
return;
};
debug!(?period, "Update tick.now and force trigger the signal");
let tick = timer.get_value_untracked();
tick.tick();
timer.force(tick)
});
let window = window().unwrap();
let Ok(handle) = window.set_interval_with_callback_and_timeout_and_arguments_0(
closure.as_ref().unchecked_ref(),
period.as_millis() as i32,
) else {
warn!("Can't create interval timer");
return timer;
};
let tick = timer.get_value_untracked();
tick.set_on_drop(AbortTickOnDrop { closure, handle });
return timer;
}
struct WeakTimer(XSignalWeak<Tick>);
unsafe impl Send for WeakTimer {}
unsafe impl Sync for WeakTimer {}