use crate::def::{CtorOf, DefKind, Res};
use crate::def_id::DefId;
use crate::hir::{self, HirId, PatKind};
use rustc_span::symbol::Ident;
use rustc_span::Span;

use std::iter::{Enumerate, ExactSizeIterator};

pub struct EnumerateAndAdjust<I> {
    enumerate: Enumerate<I>,
    gap_pos: usize,
    gap_len: usize,
}

impl<I> Iterator for EnumerateAndAdjust<I>
where
    I: Iterator,
{
    type Item = (usize, <I as Iterator>::Item);

    fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
        self.enumerate
            .next()
            .map(|(i, elem)| (if i < self.gap_pos { i } else { i + self.gap_len }, elem))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.enumerate.size_hint()
    }
}

pub trait EnumerateAndAdjustIterator {
    fn enumerate_and_adjust(
        self,
        expected_len: usize,
        gap_pos: Option<usize>,
    ) -> EnumerateAndAdjust<Self>
    where
        Self: Sized;
}

impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
    fn enumerate_and_adjust(
        self,
        expected_len: usize,
        gap_pos: Option<usize>,
    ) -> EnumerateAndAdjust<Self>
    where
        Self: Sized,
    {
        let actual_len = self.len();
        EnumerateAndAdjust {
            enumerate: self.enumerate(),
            gap_pos: gap_pos.unwrap_or(expected_len),
            gap_len: expected_len - actual_len,
        }
    }
}

impl hir::Pat<'_> {
    pub fn is_refutable(&self) -> bool {
        match self.kind {
            PatKind::Lit(_)
            | PatKind::Range(..)
            | PatKind::Path(hir::QPath::Resolved(Some(..), _) | hir::QPath::TypeRelative(..)) => {
                true
            }

            PatKind::Path(hir::QPath::Resolved(_, ref path))
            | PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..)
            | PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => match path.res {
                Res::Def(DefKind::Variant, _) => true,
                _ => false,
            },
            PatKind::Slice(..) => true,
            _ => false,
        }
    }

    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
    /// `match foo() { Some(a) => (), None => () }`
    pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, Ident)) {
        self.walk_always(|p| {
            if let PatKind::Binding(binding_mode, _, ident, _) = p.kind {
                f(binding_mode, p.hir_id, p.span, ident);
            }
        });
    }

    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
    /// `match foo() { Some(a) => (), None => () }`.
    ///
    /// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited.
    pub fn each_binding_or_first(
        &self,
        f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, Ident),
    ) {
        self.walk(|p| match &p.kind {
            PatKind::Or(ps) => {
                ps[0].each_binding_or_first(f);
                false
            }
            PatKind::Binding(bm, _, ident, _) => {
                f(*bm, p.hir_id, p.span, *ident);
                true
            }
            _ => true,
        })
    }

    /// Checks if the pattern contains any patterns that bind something to
    /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
    pub fn contains_bindings(&self) -> bool {
        self.satisfies(|p| match p.kind {
            PatKind::Binding(..) => true,
            _ => false,
        })
    }

    /// Checks if the pattern contains any patterns that bind something to
    /// an ident or wildcard, e.g., `foo`, or `Foo(_)`, `foo @ Bar(..)`,
    pub fn contains_bindings_or_wild(&self) -> bool {
        self.satisfies(|p| match p.kind {
            PatKind::Binding(..) | PatKind::Wild => true,
            _ => false,
        })
    }

    /// Checks if the pattern satisfies the given predicate on some sub-pattern.
    fn satisfies(&self, pred: impl Fn(&hir::Pat<'_>) -> bool) -> bool {
        let mut satisfies = false;
        self.walk_short(|p| {
            if pred(p) {
                satisfies = true;
                false // Found one, can short circuit now.
            } else {
                true
            }
        });
        satisfies
    }

    pub fn simple_ident(&self) -> Option<Ident> {
        match self.kind {
            PatKind::Binding(
                hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable,
                _,
                ident,
                None,
            ) => Some(ident),
            _ => None,
        }
    }

    /// Returns variants that are necessary to exist for the pattern to match.
    pub fn necessary_variants(&self) -> Vec<DefId> {
        let mut variants = vec![];
        self.walk(|p| match &p.kind {
            PatKind::Or(_) => false,
            PatKind::Path(hir::QPath::Resolved(_, path))
            | PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..)
            | PatKind::Struct(hir::QPath::Resolved(_, path), ..) => {
                if let Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), id) =
                    path.res
                {
                    variants.push(id);
                }
                true
            }
            _ => true,
        });
        variants.sort();
        variants.dedup();
        variants
    }

    /// Checks if the pattern contains any `ref` or `ref mut` bindings, and if
    /// yes whether it contains mutable or just immutables ones.
    //
    // FIXME(tschottdorf): this is problematic as the HIR is being scraped, but
    // ref bindings are be implicit after #42640 (default match binding modes). See issue #44848.
    pub fn contains_explicit_ref_binding(&self) -> Option<hir::Mutability> {
        let mut result = None;
        self.each_binding(|annotation, _, _, _| match annotation {
            hir::BindingAnnotation::Ref => match result {
                None | Some(hir::Mutability::Not) => result = Some(hir::Mutability::Not),
                _ => {}
            },
            hir::BindingAnnotation::RefMut => result = Some(hir::Mutability::Mut),
            _ => {}
        });
        result
    }
}
