//! 编辑器 DOM event target 的窄 helper。
//!
//! 本模块只做 EventTarget -> Element 归一化和 selector 命中判断，
//! 不处理编辑器状态、overlay 或命令分发。

use wasm_bindgen::JsCast;
use web_sys::{Element, EventTarget, HtmlElement, Node, WheelEvent};

pub(crate) fn target_element(target: EventTarget) -> Option<Element> {
    target.clone().dyn_into::<Element>().ok().or_else(|| {
        target
            .dyn_into::<Node>()
            .ok()
            .and_then(|node| node.parent_element())
    })
}

pub(crate) fn event_target_matches_selector(target: Option<EventTarget>, selector: &str) -> bool {
    target
        .and_then(target_element)
        .and_then(|element| element.closest(selector).ok().flatten())
        .is_some()
}

pub(crate) fn current_target_html_element(event: &WheelEvent) -> Option<HtmlElement> {
    event.current_target()?.dyn_into::<HtmlElement>().ok()
}

pub(crate) fn trap_scroll_inside_menu(event: &WheelEvent) {
    event.prevent_default();
    event.stop_propagation();

    let Some(menu) = current_target_html_element(event) else {
        return;
    };

    let current = f64::from(menu.scroll_top());
    let max_scroll = f64::from((menu.scroll_height() - menu.client_height()).max(0));
    let next = (current + event.delta_y()).clamp(0.0, max_scroll);
    menu.set_scroll_top(next.round() as i32);
}
