use super::{
    super::{super::cause::*, problem::*},
    r#trait::*,
};

use {std::slice::*, thin_vec::*};

impl ProblemImplementation for Problem {
    fn depth(&self) -> usize {
        self.causes.len()
    }

    fn get(&self, depth: usize) -> Option<&Cause> {
        self.causes.get(depth)
    }

    fn get_mut(&mut self, depth: usize) -> Option<&mut Cause> {
        self.causes.get_mut(depth)
    }

    fn top(&self) -> Option<&Cause> {
        self.causes.first()
    }

    fn top_mut(&mut self) -> Option<&mut Cause> {
        self.causes.first_mut()
    }

    fn root(&self) -> Option<&Cause> {
        self.causes.last()
    }

    fn root_mut(&mut self) -> Option<&mut Cause> {
        self.causes.last_mut()
    }

    fn add_top(&mut self, cause: Cause) {
        // TODO: wish this were a TinyVecDeque
        self.causes.insert(0, cause);
    }

    fn under(mut self, mut problem: Problem) -> Self {
        self.causes.append(&mut problem.causes);
        problem.causes = self.causes;
        problem
    }

    fn above(mut self, mut problem: Problem) -> Self {
        problem.causes.append(&mut self.causes);
        problem
    }
}

impl IntoIterator for Problem {
    type Item = Cause;
    type IntoIter = IntoIter<Cause>;

    fn into_iter(self) -> Self::IntoIter {
        self.causes.into_iter()
    }
}

impl<'this> IntoIterator for &'this Problem {
    type Item = &'this Cause;
    type IntoIter = Iter<'this, Cause>;

    fn into_iter(self) -> Self::IntoIter {
        self.causes.iter()
    }
}

impl<'this> IntoIterator for &'this mut Problem {
    type Item = &'this mut Cause;
    type IntoIter = IterMut<'this, Cause>;

    fn into_iter(self) -> Self::IntoIter {
        self.causes.iter_mut()
    }
}
