use std::borrow::Borrow;
use std::cmp::Ordering;
use std::mem;
use std::ops::{Bound, RangeBounds};
use typenum::{Add1, Unsigned};
use crate::config::OrdChunkSize as NodeSize;
use crate::nodes::sized_chunk::Chunk;
use crate::util::{clone_ref, Ref};
use self::Insert::*;
use self::InsertAction::*;
const NODE_SIZE: usize = NodeSize::USIZE;
const MEDIAN: usize = (NODE_SIZE + 1) >> 1;
pub trait BTreeValue {
    type Key;
    fn ptr_eq(&self, other: &Self) -> bool;
    fn search_key<BK>(slice: &[Self], key: &BK) -> Result<usize, usize>
    where
        BK: Ord + ?Sized,
        Self: Sized,
        Self::Key: Borrow<BK>;
    fn search_value(slice: &[Self], value: &Self) -> Result<usize, usize>
    where
        Self: Sized;
    fn cmp_keys<BK>(&self, other: &BK) -> Ordering
    where
        BK: Ord + ?Sized,
        Self::Key: Borrow<BK>;
    fn cmp_values(&self, other: &Self) -> Ordering;
}
pub struct Node<A> {
    keys: Chunk<A, NodeSize>,
    children: Chunk<Option<Ref<Node<A>>>, Add1<NodeSize>>,
}
pub enum Insert<A> {
    Added,
    Replaced(A),
    Update(Node<A>),
    Split(Node<A>, A, Node<A>),
}
enum InsertAction<A> {
    AddedAction,
    ReplacedAction(A),
    InsertAt,
    InsertSplit(Node<A>, A, Node<A>),
}
pub enum Remove<A> {
    NoChange,
    Removed(A),
    Update(A, Node<A>),
}
enum RemoveAction {
    DeleteAt(usize),
    PullUp(usize, usize, usize),
    Merge(usize),
    StealFromLeft(usize),
    StealFromRight(usize),
    MergeFirst(usize),
    ContinueDown(usize),
}
impl<A> Clone for Node<A>
where
    A: Clone,
{
    fn clone(&self) -> Self {
        Node {
            keys: self.keys.clone(),
            children: self.children.clone(),
        }
    }
}
impl<A> Default for Node<A> {
    fn default() -> Self {
        Node {
            keys: Chunk::new(),
            children: Chunk::unit(None),
        }
    }
}
impl<A> Node<A> {
    #[inline]
    fn has_room(&self) -> bool {
        self.keys.len() < NODE_SIZE
    }
    #[inline]
    fn too_small(&self) -> bool {
        self.keys.len() < MEDIAN
    }
    #[inline]
    fn is_leaf(&self) -> bool {
        self.children[0].is_none()
    }
    #[inline]
    pub fn new() -> Self {
        Self::default()
    }
    #[inline]
    pub fn unit(value: A) -> Self {
        Node {
            keys: Chunk::unit(value),
            children: Chunk::pair(None, None),
        }
    }
    #[inline]
    pub fn from_split(left: Node<A>, median: A, right: Node<A>) -> Self {
        Node {
            keys: Chunk::unit(median),
            children: Chunk::pair(Some(Ref::from(left)), Some(Ref::from(right))),
        }
    }
    pub fn min(&self) -> Option<&A> {
        match self.children.first().unwrap() {
            None => self.keys.first(),
            Some(ref child) => child.min(),
        }
    }
    pub fn max(&self) -> Option<&A> {
        match self.children.last().unwrap() {
            None => self.keys.last(),
            Some(ref child) => child.max(),
        }
    }
}
impl<A: BTreeValue> Node<A> {
    fn child_contains<BK>(&self, index: usize, key: &BK) -> bool
    where
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        if let Some(Some(ref child)) = self.children.get(index) {
            child.lookup(key).is_some()
        } else {
            false
        }
    }
    pub fn lookup<BK>(&self, key: &BK) -> Option<&A>
    where
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        if self.keys.is_empty() {
            return None;
        }
        
        
        
        match A::search_key(&self.keys, key) {
            Ok(index) => Some(&self.keys[index]),
            Err(index) => match self.children[index] {
                None => None,
                Some(ref node) => node.lookup(key),
            },
        }
    }
    pub fn lookup_mut<BK>(&mut self, key: &BK) -> Option<&mut A>
    where
        A: Clone,
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        if self.keys.is_empty() {
            return None;
        }
        
        
        
        match A::search_key(&self.keys, key) {
            Ok(index) => Some(&mut self.keys[index]),
            Err(index) => match self.children[index] {
                None => None,
                Some(ref mut child_ref) => {
                    let child = Ref::make_mut(child_ref);
                    child.lookup_mut(key)
                }
            },
        }
    }
    pub fn path_first<'a, BK>(
        &'a self,
        mut path: Vec<(&'a Node<A>, usize)>,
    ) -> Vec<(&'a Node<A>, usize)>
    where
        A: 'a,
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        if self.keys.is_empty() {
            return Vec::new();
        }
        match self.children[0] {
            None => {
                path.push((self, 0));
                path
            }
            Some(ref node) => {
                path.push((self, 0));
                node.path_first(path)
            }
        }
    }
    pub fn path_last<'a, BK>(
        &'a self,
        mut path: Vec<(&'a Node<A>, usize)>,
    ) -> Vec<(&'a Node<A>, usize)>
    where
        A: 'a,
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        if self.keys.is_empty() {
            return Vec::new();
        }
        let end = self.children.len() - 1;
        match self.children[end] {
            None => {
                path.push((self, end - 1));
                path
            }
            Some(ref node) => {
                path.push((self, end));
                node.path_last(path)
            }
        }
    }
    pub fn path_next<'a, BK>(
        &'a self,
        key: &BK,
        mut path: Vec<(&'a Node<A>, usize)>,
    ) -> Vec<(&'a Node<A>, usize)>
    where
        A: 'a,
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        if self.keys.is_empty() {
            return Vec::new();
        }
        match A::search_key(&self.keys, key) {
            Ok(index) => {
                path.push((self, index));
                path
            }
            Err(index) => match self.children[index] {
                None => match self.keys.get(index) {
                    Some(_) => {
                        path.push((self, index));
                        path
                    }
                    None => Vec::new(),
                },
                Some(ref node) => {
                    path.push((self, index));
                    node.path_next(key, path)
                }
            },
        }
    }
    pub fn path_prev<'a, BK>(
        &'a self,
        key: &BK,
        mut path: Vec<(&'a Node<A>, usize)>,
    ) -> Vec<(&'a Node<A>, usize)>
    where
        A: 'a,
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        if self.keys.is_empty() {
            return Vec::new();
        }
        match A::search_key(&self.keys, key) {
            Ok(index) => {
                path.push((self, index));
                path
            }
            Err(index) => match self.children[index] {
                None if index == 0 => Vec::new(),
                None => match self.keys.get(index - 1) {
                    Some(_) => {
                        path.push((self, index));
                        path
                    }
                    None => Vec::new(),
                },
                Some(ref node) => {
                    path.push((self, index));
                    node.path_prev(key, path)
                }
            },
        }
    }
    fn split(
        &mut self,
        value: A,
        ins_left: Option<Node<A>>,
        ins_right: Option<Node<A>>,
    ) -> Insert<A> {
        let left_child = ins_left.map(Ref::from);
        let right_child = ins_right.map(Ref::from);
        let index = A::search_value(&self.keys, &value).unwrap_err();
        let mut left_keys;
        let mut left_children;
        let mut right_keys;
        let mut right_children;
        let median;
        if index < MEDIAN {
            self.children[index] = left_child;
            left_keys = Chunk::from_front(&mut self.keys, index);
            left_keys.push_back(value);
            left_keys.drain_from_front(&mut self.keys, MEDIAN - index - 1);
            left_children = Chunk::from_front(&mut self.children, index + 1);
            left_children.push_back(right_child);
            left_children.drain_from_front(&mut self.children, MEDIAN - index - 1);
            median = self.keys.pop_front();
            right_keys = Chunk::drain_from(&mut self.keys);
            right_children = Chunk::drain_from(&mut self.children);
        } else if index > MEDIAN {
            self.children[index] = left_child;
            left_keys = Chunk::from_front(&mut self.keys, MEDIAN);
            left_children = Chunk::from_front(&mut self.children, MEDIAN + 1);
            median = self.keys.pop_front();
            right_keys = Chunk::from_front(&mut self.keys, index - MEDIAN - 1);
            right_keys.push_back(value);
            right_keys.append(&mut self.keys);
            right_children = Chunk::from_front(&mut self.children, index - MEDIAN);
            right_children.push_back(right_child);
            right_children.append(&mut self.children);
        } else {
            left_keys = Chunk::from_front(&mut self.keys, MEDIAN);
            left_children = Chunk::from_front(&mut self.children, MEDIAN);
            left_children.push_back(left_child);
            median = value;
            right_keys = Chunk::drain_from(&mut self.keys);
            right_children = Chunk::drain_from(&mut self.children);
            right_children[0] = right_child;
        }
        debug_assert!(left_keys.len() == MEDIAN);
        debug_assert!(left_children.len() == MEDIAN + 1);
        debug_assert!(right_keys.len() == MEDIAN);
        debug_assert!(right_children.len() == MEDIAN + 1);
        Split(
            Node {
                keys: left_keys,
                children: left_children,
            },
            median,
            Node {
                keys: right_keys,
                children: right_children,
            },
        )
    }
    fn merge(middle: A, left: Node<A>, mut right: Node<A>) -> Node<A> {
        let mut keys = left.keys;
        keys.push_back(middle);
        keys.append(&mut right.keys);
        let mut children = left.children;
        children.append(&mut right.children);
        Node { keys, children }
    }
    fn pop_min(&mut self) -> (A, Option<Ref<Node<A>>>) {
        let value = self.keys.pop_front();
        let child = self.children.pop_front();
        (value, child)
    }
    fn pop_max(&mut self) -> (A, Option<Ref<Node<A>>>) {
        let value = self.keys.pop_back();
        let child = self.children.pop_back();
        (value, child)
    }
    fn push_min(&mut self, child: Option<Ref<Node<A>>>, value: A) {
        self.keys.push_front(value);
        self.children.push_front(child);
    }
    fn push_max(&mut self, child: Option<Ref<Node<A>>>, value: A) {
        self.keys.push_back(value);
        self.children.push_back(child);
    }
    pub fn insert(&mut self, value: A) -> Insert<A>
    where
        A: Clone,
    {
        if self.keys.is_empty() {
            self.keys.push_back(value);
            self.children.push_back(None);
            return Insert::Added;
        }
        let (median, left, right) = match A::search_value(&self.keys, &value) {
            
            Ok(index) => {
                return Insert::Replaced(mem::replace(&mut self.keys[index], value));
            }
            
            Err(index) => {
                let has_room = self.has_room();
                let action = match self.children[index] {
                    
                    None => InsertAt,
                    
                    Some(ref mut child_ref) => {
                        let child = Ref::make_mut(child_ref);
                        match child.insert(value.clone()) {
                            Insert::Added => AddedAction,
                            Insert::Replaced(value) => ReplacedAction(value),
                            Insert::Update(_) => unreachable!(),
                            Insert::Split(left, median, right) => InsertSplit(left, median, right),
                        }
                    }
                };
                match action {
                    ReplacedAction(value) => return Insert::Replaced(value),
                    AddedAction => {
                        return Insert::Added;
                    }
                    InsertAt => {
                        if has_room {
                            self.keys.insert(index, value);
                            self.children.insert(index + 1, None);
                            return Insert::Added;
                        } else {
                            (value, None, None)
                        }
                    }
                    InsertSplit(left, median, right) => {
                        if has_room {
                            self.children[index] = Some(Ref::from(left));
                            self.keys.insert(index, median);
                            self.children.insert(index + 1, Some(Ref::from(right)));
                            return Insert::Added;
                        } else {
                            (median, Some(left), Some(right))
                        }
                    }
                }
            }
        };
        self.split(median, left, right)
    }
    pub fn remove<BK>(&mut self, key: &BK) -> Remove<A>
    where
        A: Clone,
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        let index = A::search_key(&self.keys, key);
        self.remove_index(index, key)
    }
    fn remove_index<BK>(&mut self, index: Result<usize, usize>, key: &BK) -> Remove<A>
    where
        A: Clone,
        BK: Ord + ?Sized,
        A::Key: Borrow<BK>,
    {
        let action = match index {
            
            Ok(index) => {
                match (&self.children[index], &self.children[index + 1]) {
                    
                    (&None, &None) => RemoveAction::DeleteAt(index),
                    
                    (&Some(ref left), _) if !left.too_small() => {
                        if left.is_leaf() {
                            RemoveAction::PullUp(left.keys.len() - 1, index, index)
                        } else {
                            RemoveAction::StealFromLeft(index + 1)
                        }
                    }
                    
                    (_, &Some(ref right)) if !right.too_small() => {
                        if right.is_leaf() {
                            RemoveAction::PullUp(0, index, index + 1)
                        } else {
                            RemoveAction::StealFromRight(index)
                        }
                    }
                    
                    (&Some(_), &Some(_)) => RemoveAction::Merge(index),
                    
                    _ => unreachable!(),
                }
            }
            
            Err(index) => match self.children[index] {
                
                None => return Remove::NoChange,
                
                Some(ref child) if child.too_small() => {
                    let left = if index > 0 {
                        self.children.get(index - 1)
                    } else {
                        None
                    }; 
                    match (left, self.children.get(index + 1)) {
                        
                        (Some(&Some(ref old_left)), _) if !old_left.too_small() => {
                            RemoveAction::StealFromLeft(index)
                        }
                        
                        (_, Some(&Some(ref old_right))) if !old_right.too_small() => {
                            RemoveAction::StealFromRight(index)
                        }
                        
                        
                        (_, Some(&Some(_))) => RemoveAction::MergeFirst(index),
                        
                        (Some(&Some(_)), _) => RemoveAction::MergeFirst(index - 1),
                        
                        _ => unreachable!(),
                    }
                }
                
                Some(_) => RemoveAction::ContinueDown(index),
            },
        };
        match action {
            RemoveAction::DeleteAt(index) => {
                let pair = self.keys.remove(index);
                self.children.remove(index);
                Remove::Removed(pair)
            }
            RemoveAction::PullUp(target_index, pull_to, child_index) => {
                let children = &mut self.children;
                let mut update = None;
                let mut value;
                if let Some(&mut Some(ref mut child_ref)) = children.get_mut(child_index) {
                    let child = Ref::make_mut(child_ref);
                    match child.remove_index(Ok(target_index), key) {
                        Remove::NoChange => unreachable!(),
                        Remove::Removed(pulled_value) => {
                            value = self.keys.set(pull_to, pulled_value);
                        }
                        Remove::Update(pulled_value, new_child) => {
                            value = self.keys.set(pull_to, pulled_value);
                            update = Some(new_child);
                        }
                    }
                } else {
                    unreachable!()
                }
                if let Some(new_child) = update {
                    children[child_index] = Some(Ref::from(new_child));
                }
                Remove::Removed(value)
            }
            RemoveAction::Merge(index) => {
                let left = self.children.remove(index).unwrap();
                let right = mem::replace(&mut self.children[index], None).unwrap();
                let value = self.keys.remove(index);
                let mut merged_child = Node::merge(value, clone_ref(left), clone_ref(right));
                let (removed, new_child) = match merged_child.remove(key) {
                    Remove::NoChange => unreachable!(),
                    Remove::Removed(removed) => (removed, merged_child),
                    Remove::Update(removed, updated_child) => (removed, updated_child),
                };
                if self.keys.is_empty() {
                    
                    Remove::Update(removed, new_child)
                } else {
                    self.children[index] = Some(Ref::from(new_child));
                    Remove::Removed(removed)
                }
            }
            RemoveAction::StealFromLeft(index) => {
                let mut update = None;
                let mut out_value;
                {
                    let mut children = self.children.as_mut_slice()[index - 1..=index]
                        .iter_mut()
                        .map(|n| {
                            if let Some(ref mut o) = *n {
                                o
                            } else {
                                unreachable!()
                            }
                        });
                    let left = Ref::make_mut(children.next().unwrap());
                    let child = Ref::make_mut(children.next().unwrap());
                    
                    child.push_min(
                        left.children.last().unwrap().clone(),
                        self.keys[index - 1].clone(),
                    );
                    match child.remove(key) {
                        Remove::NoChange => {
                            
                            child.pop_min();
                            return Remove::NoChange;
                        }
                        Remove::Removed(value) => {
                            
                            let (left_value, _) = left.pop_max();
                            self.keys[index - 1] = left_value;
                            out_value = value;
                        }
                        Remove::Update(value, new_child) => {
                            
                            let (left_value, _) = left.pop_max();
                            self.keys[index - 1] = left_value;
                            update = Some(new_child);
                            out_value = value;
                        }
                    }
                }
                if let Some(new_child) = update {
                    self.children[index] = Some(Ref::from(new_child));
                }
                Remove::Removed(out_value)
            }
            RemoveAction::StealFromRight(index) => {
                let mut update = None;
                let mut out_value;
                {
                    let mut children = self.children.as_mut_slice()[index..index + 2]
                        .iter_mut()
                        .map(|n| {
                            if let Some(ref mut o) = *n {
                                o
                            } else {
                                unreachable!()
                            }
                        });
                    let child = Ref::make_mut(children.next().unwrap());
                    let right = Ref::make_mut(children.next().unwrap());
                    
                    child.push_max(right.children[0].clone(), self.keys[index].clone());
                    match child.remove(key) {
                        Remove::NoChange => {
                            
                            child.pop_max();
                            return Remove::NoChange;
                        }
                        Remove::Removed(value) => {
                            
                            let (right_value, _) = right.pop_min();
                            self.keys[index] = right_value;
                            out_value = value;
                        }
                        Remove::Update(value, new_child) => {
                            
                            let (right_value, _) = right.pop_min();
                            self.keys[index] = right_value;
                            update = Some(new_child);
                            out_value = value;
                        }
                    }
                }
                if let Some(new_child) = update {
                    self.children[index] = Some(Ref::from(new_child));
                }
                Remove::Removed(out_value)
            }
            RemoveAction::MergeFirst(index) => {
                if self.keys[index].cmp_keys(key) != Ordering::Equal
                    && !self.child_contains(index, key)
                    && !self.child_contains(index + 1, key)
                {
                    return Remove::NoChange;
                }
                let left = self.children.remove(index).unwrap();
                let right = mem::replace(&mut self.children[index], None).unwrap();
                let middle = self.keys.remove(index);
                let mut merged = Node::merge(middle, clone_ref(left), clone_ref(right));
                let mut update;
                let mut out_value;
                match merged.remove(key) {
                    Remove::NoChange => {
                        panic!("nodes::btree::Node::remove: caught an absent key too late while merging");
                    }
                    Remove::Removed(value) => {
                        if self.keys.is_empty() {
                            return Remove::Update(value, merged);
                        }
                        update = merged;
                        out_value = value;
                    }
                    Remove::Update(value, new_child) => {
                        if self.keys.is_empty() {
                            return Remove::Update(value, new_child);
                        }
                        update = new_child;
                        out_value = value;
                    }
                }
                self.children[index] = Some(Ref::from(update));
                Remove::Removed(out_value)
            }
            RemoveAction::ContinueDown(index) => {
                let mut update = None;
                let mut out_value;
                if let Some(&mut Some(ref mut child_ref)) = self.children.get_mut(index) {
                    let child = Ref::make_mut(child_ref);
                    match child.remove(key) {
                        Remove::NoChange => return Remove::NoChange,
                        Remove::Removed(value) => {
                            out_value = value;
                        }
                        Remove::Update(value, new_child) => {
                            update = Some(new_child);
                            out_value = value;
                        }
                    }
                } else {
                    unreachable!()
                }
                if let Some(new_child) = update {
                    self.children[index] = Some(Ref::from(new_child));
                }
                Remove::Removed(out_value)
            }
        }
    }
}
pub struct Iter<'a, A: 'a> {
    fwd_path: Vec<(&'a Node<A>, usize)>,
    back_path: Vec<(&'a Node<A>, usize)>,
    pub(crate) remaining: usize,
}
impl<'a, A: 'a + BTreeValue> Iter<'a, A> {
    pub fn new<R, BK>(root: &'a Node<A>, size: usize, range: R) -> Self
    where
        R: RangeBounds<BK>,
        A::Key: Borrow<BK>,
        BK: Ord + ?Sized,
    {
        let fwd_path = match range.start_bound() {
            Bound::Included(key) => root.path_next(key, Vec::new()),
            Bound::Excluded(key) => {
                let mut path = root.path_next(key, Vec::new());
                if let Some(value) = Self::get(&path) {
                    if value.cmp_keys(key) == Ordering::Equal {
                        Self::step_forward(&mut path);
                    }
                }
                path
            }
            Bound::Unbounded => root.path_first(Vec::new()),
        };
        let back_path = match range.end_bound() {
            Bound::Included(key) => root.path_prev(key, Vec::new()),
            Bound::Excluded(key) => {
                let mut path = root.path_prev(key, Vec::new());
                if let Some(value) = Self::get(&path) {
                    if value.cmp_keys(key) == Ordering::Equal {
                        Self::step_back(&mut path);
                    }
                }
                path
            }
            Bound::Unbounded => root.path_last(Vec::new()),
        };
        Iter {
            fwd_path,
            back_path,
            remaining: size,
        }
    }
    fn get(path: &[(&'a Node<A>, usize)]) -> Option<&'a A> {
        match path.last() {
            Some((node, index)) => Some(&node.keys[*index]),
            None => None,
        }
    }
    fn step_forward(path: &mut Vec<(&'a Node<A>, usize)>) -> Option<&'a A> {
        match path.pop() {
            Some((node, index)) => {
                let index = index + 1;
                match node.children[index] {
                    
                    Some(ref child) => {
                        path.push((node, index));
                        path.push((child, 0));
                        let mut node = child;
                        while let Some(ref left_child) = node.children[0] {
                            path.push((left_child, 0));
                            node = left_child;
                        }
                        Some(&node.keys[0])
                    }
                    None => match node.keys.get(index) {
                        
                        value @ Some(_) => {
                            path.push((node, index));
                            value
                        }
                        
                        None => loop {
                            match path.pop() {
                                None => {
                                    return None;
                                }
                                Some((node, index)) => {
                                    if let value @ Some(_) = node.keys.get(index) {
                                        path.push((node, index));
                                        return value;
                                    }
                                }
                            }
                        },
                    },
                }
            }
            None => None,
        }
    }
    fn step_back(path: &mut Vec<(&'a Node<A>, usize)>) -> Option<&'a A> {
        match path.pop() {
            Some((node, index)) => match node.children[index] {
                Some(ref child) => {
                    path.push((node, index));
                    let mut end = child.keys.len() - 1;
                    path.push((child, end));
                    let mut node = child;
                    while let Some(ref right_child) = node.children[end + 1] {
                        end = right_child.keys.len() - 1;
                        path.push((right_child, end));
                        node = right_child;
                    }
                    Some(&node.keys[end])
                }
                None => {
                    if index == 0 {
                        loop {
                            match path.pop() {
                                None => {
                                    return None;
                                }
                                Some((node, index)) => {
                                    if index > 0 {
                                        let index = index - 1;
                                        path.push((node, index));
                                        return Some(&node.keys[index]);
                                    }
                                }
                            }
                        }
                    } else {
                        let index = index - 1;
                        path.push((node, index));
                        Some(&node.keys[index])
                    }
                }
            },
            None => None,
        }
    }
}
impl<'a, A: 'a + BTreeValue> Iterator for Iter<'a, A> {
    type Item = &'a A;
    fn next(&mut self) -> Option<Self::Item> {
        match Iter::get(&self.fwd_path) {
            None => None,
            Some(value) => match Iter::get(&self.back_path) {
                Some(last_value) if value.cmp_values(last_value) == Ordering::Greater => None,
                None => None,
                Some(_) => {
                    Iter::step_forward(&mut self.fwd_path);
                    self.remaining -= 1;
                    Some(value)
                }
            },
        }
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        
        (0, None)
    }
}
impl<'a, A: 'a + BTreeValue> DoubleEndedIterator for Iter<'a, A> {
    fn next_back(&mut self) -> Option<Self::Item> {
        match Iter::get(&self.back_path) {
            None => None,
            Some(value) => match Iter::get(&self.fwd_path) {
                Some(last_value) if value.cmp_values(last_value) == Ordering::Less => None,
                None => None,
                Some(_) => {
                    Iter::step_back(&mut self.back_path);
                    self.remaining -= 1;
                    Some(value)
                }
            },
        }
    }
}
enum ConsumingIterItem<A> {
    Consider(Node<A>),
    Yield(A),
}
pub struct ConsumingIter<A> {
    fwd_last: Option<A>,
    fwd_stack: Vec<ConsumingIterItem<A>>,
    back_last: Option<A>,
    back_stack: Vec<ConsumingIterItem<A>>,
    remaining: usize,
}
impl<A: Clone> ConsumingIter<A> {
    pub fn new(root: &Node<A>, total: usize) -> Self {
        ConsumingIter {
            fwd_last: None,
            fwd_stack: vec![ConsumingIterItem::Consider(root.clone())],
            back_last: None,
            back_stack: vec![ConsumingIterItem::Consider(root.clone())],
            remaining: total,
        }
    }
    fn push_node(stack: &mut Vec<ConsumingIterItem<A>>, maybe_node: Option<Ref<Node<A>>>) {
        if let Some(node) = maybe_node {
            stack.push(ConsumingIterItem::Consider(clone_ref(node)))
        }
    }
    fn push(stack: &mut Vec<ConsumingIterItem<A>>, mut node: Node<A>) {
        for _n in 0..node.keys.len() {
            ConsumingIter::push_node(stack, node.children.pop_back());
            stack.push(ConsumingIterItem::Yield(node.keys.pop_back()));
        }
        ConsumingIter::push_node(stack, node.children.pop_back());
    }
    fn push_fwd(&mut self, node: Node<A>) {
        ConsumingIter::push(&mut self.fwd_stack, node)
    }
    fn push_node_back(&mut self, maybe_node: Option<Ref<Node<A>>>) {
        if let Some(node) = maybe_node {
            self.back_stack
                .push(ConsumingIterItem::Consider(clone_ref(node)))
        }
    }
    fn push_back(&mut self, mut node: Node<A>) {
        for _i in 0..node.keys.len() {
            self.push_node_back(node.children.pop_front());
            self.back_stack
                .push(ConsumingIterItem::Yield(node.keys.pop_front()));
        }
        self.push_node_back(node.children.pop_back());
    }
}
impl<A> Iterator for ConsumingIter<A>
where
    A: BTreeValue + Clone,
{
    type Item = A;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.fwd_stack.pop() {
                None => {
                    self.remaining = 0;
                    return None;
                }
                Some(ConsumingIterItem::Consider(node)) => self.push_fwd(node),
                Some(ConsumingIterItem::Yield(value)) => {
                    if let Some(ref last) = self.back_last {
                        if value.cmp_values(last) != Ordering::Less {
                            self.fwd_stack.clear();
                            self.back_stack.clear();
                            self.remaining = 0;
                            return None;
                        }
                    }
                    self.remaining -= 1;
                    self.fwd_last = Some(value.clone());
                    return Some(value);
                }
            }
        }
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.remaining, Some(self.remaining))
    }
}
impl<A> DoubleEndedIterator for ConsumingIter<A>
where
    A: BTreeValue + Clone,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        loop {
            match self.back_stack.pop() {
                None => {
                    self.remaining = 0;
                    return None;
                }
                Some(ConsumingIterItem::Consider(node)) => self.push_back(node),
                Some(ConsumingIterItem::Yield(value)) => {
                    if let Some(ref last) = self.fwd_last {
                        if value.cmp_values(last) != Ordering::Greater {
                            self.fwd_stack.clear();
                            self.back_stack.clear();
                            self.remaining = 0;
                            return None;
                        }
                    }
                    self.remaining -= 1;
                    self.back_last = Some(value.clone());
                    return Some(value);
                }
            }
        }
    }
}
impl<A: BTreeValue + Clone> ExactSizeIterator for ConsumingIter<A> {}
pub struct DiffIter<'a, A: 'a> {
    old_stack: Vec<IterItem<'a, A>>,
    new_stack: Vec<IterItem<'a, A>>,
}
#[derive(PartialEq, Eq)]
pub enum DiffItem<'a, A: 'a> {
    Add(&'a A),
    Update { old: &'a A, new: &'a A },
    Remove(&'a A),
}
enum IterItem<'a, A: 'a> {
    Consider(&'a Node<A>),
    Yield(&'a A),
}
impl<'a, A: 'a> DiffIter<'a, A> {
    pub fn new(old: &'a Node<A>, new: &'a Node<A>) -> Self {
        DiffIter {
            old_stack: if old.keys.is_empty() {
                Vec::new()
            } else {
                vec![IterItem::Consider(old)]
            },
            new_stack: if new.keys.is_empty() {
                Vec::new()
            } else {
                vec![IterItem::Consider(new)]
            },
        }
    }
    fn push_node(stack: &mut Vec<IterItem<'a, A>>, maybe_node: &'a Option<Ref<Node<A>>>) {
        if let Some(ref node) = *maybe_node {
            stack.push(IterItem::Consider(&node))
        }
    }
    fn push(stack: &mut Vec<IterItem<'a, A>>, node: &'a Node<A>) {
        for n in 0..node.keys.len() {
            let i = node.keys.len() - n;
            Self::push_node(stack, &node.children[i]);
            stack.push(IterItem::Yield(&node.keys[i - 1]));
        }
        Self::push_node(stack, &node.children[0]);
    }
}
impl<'a, A> Iterator for DiffIter<'a, A>
where
    A: 'a + BTreeValue + PartialEq,
{
    type Item = DiffItem<'a, A>;
    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match (self.old_stack.pop(), self.new_stack.pop()) {
                (None, None) => return None,
                (None, Some(new)) => match new {
                    IterItem::Consider(new) => Self::push(&mut self.new_stack, &new),
                    IterItem::Yield(new) => return Some(DiffItem::Add(new)),
                },
                (Some(old), None) => match old {
                    IterItem::Consider(old) => Self::push(&mut self.old_stack, &old),
                    IterItem::Yield(old) => return Some(DiffItem::Remove(old)),
                },
                (Some(old), Some(new)) => match (old, new) {
                    (IterItem::Consider(old), IterItem::Consider(new)) => {
                        match old.keys[0].cmp_values(&new.keys[0]) {
                            Ordering::Less => {
                                Self::push(&mut self.old_stack, &old);
                                self.new_stack.push(IterItem::Consider(new));
                            }
                            Ordering::Greater => {
                                self.old_stack.push(IterItem::Consider(old));
                                Self::push(&mut self.new_stack, &new);
                            }
                            Ordering::Equal => {
                                Self::push(&mut self.old_stack, &old);
                                Self::push(&mut self.new_stack, &new);
                            }
                        }
                    }
                    (IterItem::Consider(old), IterItem::Yield(new)) => {
                        Self::push(&mut self.old_stack, &old);
                        self.new_stack.push(IterItem::Yield(new));
                    }
                    (IterItem::Yield(old), IterItem::Consider(new)) => {
                        self.old_stack.push(IterItem::Yield(old));
                        Self::push(&mut self.new_stack, &new);
                    }
                    (IterItem::Yield(old), IterItem::Yield(new)) => match old.cmp_values(&new) {
                        Ordering::Less => {
                            self.new_stack.push(IterItem::Yield(new));
                            return Some(DiffItem::Remove(old));
                        }
                        Ordering::Equal => {
                            if old != new {
                                return Some(DiffItem::Update { old, new });
                            }
                        }
                        Ordering::Greater => {
                            self.old_stack.push(IterItem::Yield(old));
                            return Some(DiffItem::Add(new));
                        }
                    },
                },
            }
        }
    }
}