use super::{for_both, Either, Left, Right};
use core::iter;

macro_rules! wrap_either {
    ($value:expr => $( $tail:tt )*) => {
        match $value {
            Left(inner) => inner.map(Left) $($tail)*,
            Right(inner) => inner.map(Right) $($tail)*,
        }
    };
}

/// Iterator that maps left or right iterators to corresponding `Either`-wrapped items.
///
/// This struct is created by the [`Either::factor_into_iter`],
/// [`factor_iter`][Either::factor_iter],
/// and [`factor_iter_mut`][Either::factor_iter_mut] methods.
#[derive(Clone, Debug)]
pub struct IterEither<L, R> {
    inner: Either<L, R>,
}

impl<L, R> IterEither<L, R> {
    pub(crate) fn new(inner: Either<L, R>) -> Self {
        IterEither { inner }
    }
}

impl<L, R, A> Extend<A> for Either<L, R>
where
    L: Extend<A>,
    R: Extend<A>,
{
    fn extend<T>(&mut self, iter: T)
    where
        T: IntoIterator<Item = A>,
    {
        for_both!(*self, ref mut inner => inner.extend(iter))
    }
}

/// `Either<L, R>` is an iterator if both `L` and `R` are iterators.
impl<L, R> Iterator for Either<L, R>
where
    L: Iterator,
    R: Iterator<Item = L::Item>,
{
    type Item = L::Item;

    fn next(&mut self) -> Option<Self::Item> {
        for_both!(*self, ref mut inner => inner.next())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        for_both!(*self, ref inner => inner.size_hint())
    }

    fn fold<Acc, G>(self, init: Acc, f: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        for_both!(self, inner => inner.fold(init, f))
    }

    fn for_each<F>(self, f: F)
    where
        F: FnMut(Self::Item),
    {
        for_both!(self, inner => inner.for_each(f))
    }

    fn count(self) -> usize {
        for_both!(self, inner => inner.count())
    }

    fn last(self) -> Option<Self::Item> {
        for_both!(self, inner => inner.last())
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        for_both!(*self, ref mut inner => inner.nth(n))
    }

    fn collect<B>(self) -> B
    where
        B: iter::FromIterator<Self::Item>,
    {
        for_both!(self, inner => inner.collect())
    }

    fn partition<B, F>(self, f: F) -> (B, B)
    where
        B: Default + Extend<Self::Item>,
        F: FnMut(&Self::Item) -> bool,
    {
        for_both!(self, inner => inner.partition(f))
    }

    fn all<F>(&mut self, f: F) -> bool
    where
        F: FnMut(Self::Item) -> bool,
    {
        for_both!(*self, ref mut inner => inner.all(f))
    }

    fn any<F>(&mut self, f: F) -> bool
    where
        F: FnMut(Self::Item) -> bool,
    {
        for_both!(*self, ref mut inner => inner.any(f))
    }

    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        for_both!(*self, ref mut inner => inner.find(predicate))
    }

    fn find_map<B, F>(&mut self, f: F) -> Option<B>
    where
        F: FnMut(Self::Item) -> Option<B>,
    {
        for_both!(*self, ref mut inner => inner.find_map(f))
    }

    fn position<P>(&mut self, predicate: P) -> Option<usize>
    where
        P: FnMut(Self::Item) -> bool,
    {
        for_both!(*self, ref mut inner => inner.position(predicate))
    }
}

impl<L, R> DoubleEndedIterator for Either<L, R>
where
    L: DoubleEndedIterator,
    R: DoubleEndedIterator<Item = L::Item>,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        for_both!(*self, ref mut inner => inner.next_back())
    }

    // TODO(MSRV): This was stabilized in Rust 1.37
    // fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
    //     for_both!(*self, ref mut inner => inner.nth_back(n))
    // }

    fn rfold<Acc, G>(self, init: Acc, f: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        for_both!(self, inner => inner.rfold(init, f))
    }

    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        for_both!(*self, ref mut inner => inner.rfind(predicate))
    }
}

impl<L, R> ExactSizeIterator for Either<L, R>
where
    L: ExactSizeIterator,
    R: ExactSizeIterator<Item = L::Item>,
{
    fn len(&self) -> usize {
        for_both!(*self, ref inner => inner.len())
    }
}

impl<L, R> iter::FusedIterator for Either<L, R>
where
    L: iter::FusedIterator,
    R: iter::FusedIterator<Item = L::Item>,
{
}

impl<L, R> Iterator for IterEither<L, R>
where
    L: Iterator,
    R: Iterator,
{
    type Item = Either<L::Item, R::Item>;

    fn next(&mut self) -> Option<Self::Item> {
        Some(map_either!(self.inner, ref mut inner => inner.next()?))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        for_both!(self.inner, ref inner => inner.size_hint())
    }

    fn fold<Acc, G>(self, init: Acc, f: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        wrap_either!(self.inner => .fold(init, f))
    }

    fn for_each<F>(self, f: F)
    where
        F: FnMut(Self::Item),
    {
        wrap_either!(self.inner => .for_each(f))
    }

    fn count(self) -> usize {
        for_both!(self.inner, inner => inner.count())
    }

    fn last(self) -> Option<Self::Item> {
        Some(map_either!(self.inner, inner => inner.last()?))
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        Some(map_either!(self.inner, ref mut inner => inner.nth(n)?))
    }

    fn collect<B>(self) -> B
    where
        B: iter::FromIterator<Self::Item>,
    {
        wrap_either!(self.inner => .collect())
    }

    fn partition<B, F>(self, f: F) -> (B, B)
    where
        B: Default + Extend<Self::Item>,
        F: FnMut(&Self::Item) -> bool,
    {
        wrap_either!(self.inner => .partition(f))
    }

    fn all<F>(&mut self, f: F) -> bool
    where
        F: FnMut(Self::Item) -> bool,
    {
        wrap_either!(&mut self.inner => .all(f))
    }

    fn any<F>(&mut self, f: F) -> bool
    where
        F: FnMut(Self::Item) -> bool,
    {
        wrap_either!(&mut self.inner => .any(f))
    }

    fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        wrap_either!(&mut self.inner => .find(predicate))
    }

    fn find_map<B, F>(&mut self, f: F) -> Option<B>
    where
        F: FnMut(Self::Item) -> Option<B>,
    {
        wrap_either!(&mut self.inner => .find_map(f))
    }

    fn position<P>(&mut self, predicate: P) -> Option<usize>
    where
        P: FnMut(Self::Item) -> bool,
    {
        wrap_either!(&mut self.inner => .position(predicate))
    }
}

impl<L, R> DoubleEndedIterator for IterEither<L, R>
where
    L: DoubleEndedIterator,
    R: DoubleEndedIterator,
{
    fn next_back(&mut self) -> Option<Self::Item> {
        Some(map_either!(self.inner, ref mut inner => inner.next_back()?))
    }

    // TODO(MSRV): This was stabilized in Rust 1.37
    // fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
    //     Some(map_either!(self.inner, ref mut inner => inner.nth_back(n)?))
    // }

    fn rfold<Acc, G>(self, init: Acc, f: G) -> Acc
    where
        G: FnMut(Acc, Self::Item) -> Acc,
    {
        wrap_either!(self.inner => .rfold(init, f))
    }

    fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
    where
        P: FnMut(&Self::Item) -> bool,
    {
        wrap_either!(&mut self.inner => .rfind(predicate))
    }
}

impl<L, R> ExactSizeIterator for IterEither<L, R>
where
    L: ExactSizeIterator,
    R: ExactSizeIterator,
{
    fn len(&self) -> usize {
        for_both!(self.inner, ref inner => inner.len())
    }
}

impl<L, R> iter::FusedIterator for IterEither<L, R>
where
    L: iter::FusedIterator,
    R: iter::FusedIterator,
{
}
