use crate::mem::InMemDicomObject;
use dicom_core::DataElement;
use dicom_parser::dataset::{DataToken, IntoTokens};
use std::collections::VecDeque;
pub struct InMemObjectTokens<E> {
    tokens_pending: VecDeque<DataToken>,
    elem_iter: E,
    fused: bool,
}
impl<E> InMemObjectTokens<E>
where
    E: Iterator,
{
    pub fn new<T>(obj: T) -> Self
    where
        T: IntoIterator<IntoIter = E, Item = E::Item>,
    {
        InMemObjectTokens {
            tokens_pending: Default::default(),
            elem_iter: obj.into_iter(),
            fused: false,
        }
    }
}
impl<P, I, E> Iterator for InMemObjectTokens<E>
where
    E: Iterator<Item = DataElement<I, P>>,
    E::Item: IntoTokens,
{
    type Item = DataToken;
    fn next(&mut self) -> Option<Self::Item> {
        if self.fused {
            return None;
        }
        if let Some(token) = self.tokens_pending.pop_front() {
            return Some(token);
        }
        if let Some(elem) = self.elem_iter.next() {
            self.tokens_pending = elem.into_tokens().collect();
            self.next()
        } else {
            None
        }
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.elem_iter.size_hint().0 * 2, None)
    }
}
impl<D> IntoTokens for InMemDicomObject<D> {
    type Iter = InMemObjectTokens<<InMemDicomObject<D> as IntoIterator>::IntoIter>;
    fn into_tokens(self) -> Self::Iter {
        InMemObjectTokens::new(self)
    }
}
impl<'a, D> IntoTokens for &'a InMemDicomObject<D>
where
    D: Clone,
{
    type Iter =
        InMemObjectTokens<std::iter::Cloned<<&'a InMemDicomObject<D> as IntoIterator>::IntoIter>>;
    fn into_tokens(self) -> Self::Iter {
        InMemObjectTokens::new(self.into_iter().cloned())
    }
}