use collections::HashMap;

#[derive(Debug, Hash, PartialEq, Eq)]
pub(crate) enum SerialKind {
    DataDevice,
    InputMethod,
    MouseEnter,
    MousePress,
    KeyPress,
    /// Serial carried by the most recent `wl_keyboard.enter` event (the
    /// compositor's keyboard-focus serial). Mutter's
    /// `meta_wayland_keyboard_can_grab_surface` accepts exactly this serial
    /// when activating a focused window via xdg-activation-v1, so it must be
    /// attached to activation tokens — a stale mouse-press serial is rejected.
    KeyboardEnter,
}

#[derive(Debug)]
struct SerialData {
    serial: u32,
}

impl SerialData {
    fn new(value: u32) -> Self {
        Self { serial: value }
    }
}

#[derive(Debug)]
/// Helper for tracking of different serial kinds.
pub(crate) struct SerialTracker {
    serials: HashMap<SerialKind, SerialData>,
}

impl SerialTracker {
    pub fn new() -> Self {
        Self {
            serials: HashMap::default(),
        }
    }

    pub fn update(&mut self, kind: SerialKind, value: u32) {
        self.serials.insert(kind, SerialData::new(value));
    }

    /// Returns the latest tracked serial of the provided [`SerialKind`]
    ///
    /// Will return 0 if not tracked.
    pub fn get(&self, kind: SerialKind) -> u32 {
        self.serials
            .get(&kind)
            .map(|serial_data| serial_data.serial)
            .unwrap_or(0)
    }

    /// Returns the latest tracked serial of the provided [`SerialKind`]s
    ///
    /// Will return 0 if not tracked.
    pub fn latest_of(&self, kinds: &[SerialKind]) -> u32 {
        kinds
            .iter()
            .filter_map(|kind| self.serials.get(kind))
            .max_by_key(|serial_data| serial_data.serial)
            .map(|serial_data| serial_data.serial)
            .unwrap_or(0)
    }
}
