use std::collections::HashMap;
use std::time::{Duration, Instant};
use yog_sync::Mutex;
use jni::JNIEnv;
use yog_event::video;
const LINGER: Duration = Duration::from_secs(1);
static DRAWN: Mutex<Option<HashMap<String, (u32, Instant)>>> = Mutex::new(None);
pub(crate) fn frame(env: &mut JNIEnv, id: &str) -> Option<video::Picture> {
super::size(id)?;
let now = Instant::now();
sweep();
let handle = {
let mut drawn = DRAWN.lock();
let drawn = drawn.get_or_insert_with(HashMap::new);
match drawn.get_mut(id) {
Some((handle, at)) => {
*at = now;
Some(*handle)
}
None => super::open(&video::Open { id: id.to_owned() }).inspect(|&h| {
super::with_player(h, |p| p.play(true));
drawn.insert(id.to_owned(), (h, now));
}),
}
};
super::with_player(handle?, |p| p.frame(env)).flatten()
}
pub(crate) fn sweep() {
let now = Instant::now();
let stale: Vec<u32> = DRAWN
.lock()
.as_mut()
.map(|drawn| {
drawn
.extract_if(|_, (_, at)| now.duration_since(*at) > LINGER)
.map(|(_, (handle, _))| handle)
.collect()
})
.unwrap_or_default();
for handle in stale {
super::close(&video::Close { handle });
}
}
fn video_of(t: &str) -> Option<&str> {
t.split_once(yog_ids::sep::NAMESPACE)
.filter(|(scheme, _)| *scheme == yog_ids::image_scheme::VIDEO)
.map(|(_, id)| id)
}
pub(crate) fn body_textures(draws: &mut [yog_body::wire::Draw]) {
if !draws.iter().any(|d| video_of(&d.mesh.texture).is_some()) {
return;
}
let Some(mut env) = crate::jni_util::attached_env() else {
return;
};
for d in draws {
let Some(id) = video_of(&d.mesh.texture).map(str::to_owned) else {
continue;
};
if let Some(p) = frame(&mut env, &id) {
d.mesh.texture = p.texture;
}
}
}