use crate::trans::Trans;
use crate::state::BoxState;
#[derive(Default)]
pub struct Stack<D> {
stack: Vec<BoxState<D>>,
}
impl <D> Stack<D> {
#[must_use]
pub fn new() -> Self { Self { stack: vec![] } }
}
impl <D> Stack<D> {
#[must_use]
pub fn is_running(&self) -> bool { !self.stack.is_empty() }
#[must_use]
pub fn len(&self) -> usize {
self.stack.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.stack.is_empty()
}
}
impl <D> Stack<D> {
pub fn push(&mut self, data: &mut D, mut state: BoxState<D>) {
if let Some(curr_state) = self.stack.last_mut() {
curr_state.on_pause(data);
}
state.on_start(data);
self.stack.push(state);
}
pub fn pop(&mut self, data: &mut D) {
if let Some(mut curr_state) = self.stack.pop() {
curr_state.on_stop(data);
}
if let Some(state) = self.stack.last_mut() {
state.on_resume(data);
}
}
pub fn quit(&mut self, data: &mut D) {
while let Some(mut state) = self.stack.pop() { state.on_stop(data); }
}
}
impl <D> Stack<D> {
pub fn replace(&mut self, data: &mut D, state: BoxState<D>) {
self.pop(data);
self.push(data, state);
}
pub fn isolate(&mut self, data: &mut D, state: BoxState<D>) {
self.quit(data);
self.push(data, state);
}
}
impl <D> Stack<D> {
pub fn tick(&mut self, data: &mut D) {
let mut shadow_transitions: Vec<Trans<D>> = vec![];
for state in self.stack.iter_mut() {
shadow_transitions.push(state.on_shadow_tick(data));
};
for shadow_transition in shadow_transitions {
match shadow_transition {
Trans::Push(state) => self.push (data, state),
Trans::Pop => self.pop (data ),
Trans::Replace(state) => self.replace(data, state),
Trans::Isolate(state) => self.isolate(data, state),
Trans::None => ( ),
Trans::Quit => self.quit (data ),
}
}
let transition: Trans<D> = match self.stack.last_mut() {
Some(state) => state.on_tick(data),
None => Trans::None,
};
match transition {
Trans::Push(state) => self.push (data, state),
Trans::Pop => self.pop (data ),
Trans::Replace(state) => self.replace(data, state),
Trans::Isolate(state) => self.isolate(data, state),
Trans::None => ( ),
Trans::Quit => self.quit (data ),
};
}
}