mod key;
mod pointer;
pub mod script;

pub use key::{KeyChar, KeyCode, KeyEvent, ModifierMask, NamedKey};
pub use pointer::{
    ClickCount, DoubleClickWindow, DragThreshold, FrameInstant, PointerButton, PointerButtonMask,
    PointerSample,
};
pub use script::Script;

use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct InputSnapshot {
    pub frame: FrameInstant,
    pub pointer: Option<PointerSample>,
    pub buttons_pressed: PointerButtonMask,
    pub buttons_released: PointerButtonMask,
    pub keys_pressed: Vec<KeyEvent>,
    pub text_committed: String,
    pub modifiers: ModifierMask,
    pub double_click_window: DoubleClickWindow,
    pub drag_threshold: DragThreshold,
    pub scroll_y: f32,
}

impl InputSnapshot {
    #[must_use]
    pub fn idle(frame: FrameInstant) -> Self {
        Self {
            frame,
            pointer: None,
            buttons_pressed: PointerButtonMask::EMPTY,
            buttons_released: PointerButtonMask::EMPTY,
            keys_pressed: Vec::new(),
            text_committed: String::new(),
            modifiers: ModifierMask::NONE,
            double_click_window: DoubleClickWindow::DEFAULT,
            drag_threshold: DragThreshold::DEFAULT,
            scroll_y: 0.0,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{FrameInstant, InputSnapshot};

    #[test]
    fn idle_snapshot_has_no_input() {
        let snap = InputSnapshot::idle(FrameInstant::ZERO);
        assert!(snap.pointer.is_none());
        assert!(snap.buttons_pressed.is_empty());
        assert!(snap.buttons_released.is_empty());
        assert!(snap.keys_pressed.is_empty());
    }
}
