use std::collections::BTreeMap;
use time::Date;
use crate::model::{
AccountAction, AccountChange, AccountEvent, AccountHandle, AccountKind, AccountPath, Label,
};
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub(crate) struct AccountBook {
accounts: BTreeMap<AccountHandle, Registered>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct Registered {
path: AccountPath,
kind: AccountKind,
classes: Vec<(Date, Option<Label>)>,
}
impl AccountBook {
pub(crate) fn feed(&mut self, event: &AccountEvent) {
match &event.action {
AccountAction::Register(registration) => {
self.accounts.insert(
registration.handle,
Registered {
path: registration.path.clone(),
kind: registration.kind,
classes: vec![(event.effective, registration.class.clone())],
},
);
}
AccountAction::Change {
handle,
change: AccountChange::Class(class),
} => {
if let Some(account) = self.accounts.get_mut(handle) {
account.classes.push((event.effective, class.clone()));
}
}
AccountAction::Change { .. } => {}
}
}
pub(crate) fn get(&self, handle: AccountHandle) -> Option<&Registered> {
self.accounts.get(&handle)
}
pub(crate) fn by_path(&self) -> BTreeMap<AccountPath, (AccountHandle, AccountKind)> {
self.accounts
.iter()
.map(|(handle, account)| (account.path.clone(), (*handle, account.kind)))
.collect()
}
}
impl Registered {
pub(crate) const fn path(&self) -> &AccountPath {
&self.path
}
pub(crate) const fn kind(&self) -> AccountKind {
self.kind
}
pub(crate) fn class(&self) -> Option<&Label> {
self.classes.last().and_then(|(_, class)| class.as_ref())
}
pub(crate) fn class_on(&self, date: Date) -> Option<&Label> {
self.classes
.iter()
.rev()
.find(|(effective, _)| *effective <= date)
.or_else(|| self.classes.first())
.and_then(|(_, class)| class.as_ref())
}
}