use std::collections::{BTreeMap, BTreeSet};
use crate::types::{Action, CatchMask, Class, Usage};
pub(crate) type LockKey = (u8, u16, u8);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub(crate) enum Override {
#[default]
None,
Press,
Force,
}
impl Override {
pub(crate) fn as_action(self) -> Option<Action> {
match self {
Override::None => None,
Override::Press => Some(Action::Press),
Override::Force => Some(Action::ForceRelease),
}
}
fn applied(action: Action) -> Override {
match action {
Action::Press => Override::Press,
Action::ForceRelease => Override::Force,
Action::SoftRelease => Override::None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct DesiredState {
overrides: BTreeMap<(u8, u16), Override>, locks: BTreeSet<LockKey>,
catch: CatchMask,
}
impl Default for DesiredState {
fn default() -> Self {
DesiredState {
overrides: BTreeMap::new(),
locks: BTreeSet::new(),
catch: CatchMask::empty(),
}
}
}
impl DesiredState {
pub(crate) fn apply(&mut self, usage: Usage, action: Action) {
let key = usage.class_id();
match Override::applied(action) {
Override::None => {
self.overrides.remove(&key);
}
ov => {
self.overrides.insert(key, ov);
}
}
}
pub(crate) fn apply_lock(&mut self, key: LockKey, on: bool) {
if on {
self.locks.insert(key);
} else {
self.locks.remove(&key);
}
}
pub(crate) fn clear(&mut self) {
self.overrides.clear();
self.locks.clear();
}
pub(crate) fn set_catch(&mut self, mask: CatchMask) {
self.catch = mask;
}
pub(crate) fn catch(&self) -> CatchMask {
self.catch
}
pub(crate) fn is_idle(&self) -> bool {
self.catch.is_empty() && self.overrides.is_empty() && self.locks.is_empty()
}
pub(crate) fn held(&self) -> impl Iterator<Item = (Usage, Action)> + '_ {
self.overrides.iter().filter_map(|(&(cls, id), ov)| {
let action = ov.as_action()?;
let class = Class::from_u8(cls)?;
Some((Usage::new(class, id), action))
})
}
pub(crate) fn held_locks(&self) -> impl Iterator<Item = LockKey> + '_ {
self.locks.iter().copied()
}
}