use crate::iterators::async_iterators::AsyncIterator;
use core::marker::PhantomData;

#[allow(unused_imports)]
use crate::iterators::Detached;
use crate::iterators::iterator_trait::PrivateMRBIterator;
use crate::{MRBIterator, MutRB};

#[doc = r##"
Async version of [`Detached`].
"##]
pub struct AsyncDetached<'buf, I: AsyncIterator<'buf>, B: MutRB> {
    inner: I,
    phantom_data: PhantomData<&'buf B>,
}

unsafe impl<'buf, I: AsyncIterator<'buf>, B: MutRB> Send for AsyncDetached<'buf, I, B> {}

impl<'buf, B: MutRB<Item = T>, T, I: AsyncIterator<'buf>> AsyncDetached<'buf, I, B> {
    /// Creates [`Self`] from an [`AsyncWorkIter`].
    pub(crate) fn from_iter(iter: I) -> AsyncDetached<'buf, I, B> {
        Self {
            inner: iter,
            phantom_data: PhantomData,
        }
    }

    /// Same as [`Detached::attach`].
    pub fn attach(self) -> I {
        self.sync_index();
        self.inner
    }

    /// Same as [`Detached::sync_index`].
    pub fn sync_index(&self) {
        self.inner.inner().set_atomic_index(self.inner.index())
    }

    /// Same as [`Detached::advance`].
    ///
    /// # Safety
    /// Same as [`Detached::advance`].
    pub unsafe fn advance(&mut self, count: usize) {
        unsafe { self.inner.inner_mut().advance_local(count) };
    }

    /// Same as [`Detached::go_back`].
    ///
    /// # Safety
    /// Same as [`Detached::go_back`].
    pub unsafe fn go_back(&mut self, count: usize) {
        let idx = self.inner.inner_mut().index();
        let buf_len = self.inner.inner_mut().buf_len();

        self.inner.inner_mut().set_local_index(match idx < count {
            true => unsafe { buf_len.unchecked_sub(count).unchecked_sub(idx) },
            false => unsafe { idx.unchecked_sub(count) },
        });

        let avail = self.inner.inner_mut().cached_avail();
        self.inner
            .inner_mut()
            .set_cached_avail(unsafe { avail.unchecked_add(count) });
    }
}
