use errors::DiagnosticBuilder;
use smallvec::SmallVec;
use syntax_pos::Span;

use crate::hir;
use crate::hir::def_id::DefId;
use crate::traits::specialize::specialization_graph::NodeItem;
use crate::ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef};
use crate::ty::outlives::Component;
use crate::ty::subst::{Kind, Subst, SubstsRef};
use crate::util::nodemap::FxHashSet;

use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};

fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
    match *pred {
        ty::Predicate::Trait(ref data) =>
            ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data)),

        ty::Predicate::RegionOutlives(ref data) =>
            ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data)),

        ty::Predicate::TypeOutlives(ref data) =>
            ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data)),

        ty::Predicate::Projection(ref data) =>
            ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data)),

        ty::Predicate::WellFormed(data) =>
            ty::Predicate::WellFormed(data),

        ty::Predicate::ObjectSafe(data) =>
            ty::Predicate::ObjectSafe(data),

        ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) =>
            ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind),

        ty::Predicate::Subtype(ref data) =>
            ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data)),

        ty::Predicate::ConstEvaluatable(def_id, substs) =>
            ty::Predicate::ConstEvaluatable(def_id, substs),
    }
}

struct PredicateSet<'tcx> {
    tcx: TyCtxt<'tcx>,
    set: FxHashSet<ty::Predicate<'tcx>>,
}

impl PredicateSet<'tcx> {
    fn new(tcx: TyCtxt<'tcx>) -> Self {
        Self { tcx: tcx, set: Default::default() }
    }

    fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool {
        // We have to be careful here because we want
        //
        //    for<'a> Foo<&'a int>
        //
        // and
        //
        //    for<'b> Foo<&'b int>
        //
        // to be considered equivalent. So normalize all late-bound
        // regions before we throw things into the underlying set.
        self.set.insert(anonymize_predicate(self.tcx, pred))
    }
}

impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> {
    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
        for pred in iter {
            self.insert(pred.as_ref());
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// `Elaboration` iterator
///////////////////////////////////////////////////////////////////////////

/// "Elaboration" is the process of identifying all the predicates that
/// are implied by a source predicate. Currently this basically means
/// walking the "supertraits" and other similar assumptions. For example,
/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
/// `T: Foo`, then we know that `T: 'static`.
pub struct Elaborator<'tcx> {
    stack: Vec<ty::Predicate<'tcx>>,
    visited: PredicateSet<'tcx>,
}

pub fn elaborate_trait_ref<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_ref: ty::PolyTraitRef<'tcx>,
) -> Elaborator<'tcx> {
    elaborate_predicates(tcx, vec![trait_ref.to_predicate()])
}

pub fn elaborate_trait_refs<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Elaborator<'tcx> {
    let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()).collect();
    elaborate_predicates(tcx, predicates)
}

pub fn elaborate_predicates<'tcx>(
    tcx: TyCtxt<'tcx>,
    mut predicates: Vec<ty::Predicate<'tcx>>,
) -> Elaborator<'tcx> {
    let mut visited = PredicateSet::new(tcx);
    predicates.retain(|pred| visited.insert(pred));
    Elaborator { stack: predicates, visited }
}

impl Elaborator<'tcx> {
    pub fn filter_to_traits(self) -> FilterToTraits<Self> {
        FilterToTraits::new(self)
    }

    fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) {
        let tcx = self.visited.tcx;
        match *predicate {
            ty::Predicate::Trait(ref data) => {
                // Get predicates declared on the trait.
                let predicates = tcx.super_predicates_of(data.def_id());

                let predicates = predicates.predicates
                    .iter()
                    .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref()));
                debug!("super_predicates: data={:?} predicates={:?}",
                       data, predicates.clone());

                // Only keep those bounds that we haven't already seen.
                // This is necessary to prevent infinite recursion in some
                // cases. One common case is when people define
                // `trait Sized: Sized { }` rather than `trait Sized { }`.
                let visited = &mut self.visited;
                let predicates = predicates.filter(|pred| visited.insert(pred));

                self.stack.extend(predicates);
            }
            ty::Predicate::WellFormed(..) => {
                // Currently, we do not elaborate WF predicates,
                // although we easily could.
            }
            ty::Predicate::ObjectSafe(..) => {
                // Currently, we do not elaborate object-safe
                // predicates.
            }
            ty::Predicate::Subtype(..) => {
                // Currently, we do not "elaborate" predicates like `X <: Y`,
                // though conceivably we might.
            }
            ty::Predicate::Projection(..) => {
                // Nothing to elaborate in a projection predicate.
            }
            ty::Predicate::ClosureKind(..) => {
                // Nothing to elaborate when waiting for a closure's kind to be inferred.
            }
            ty::Predicate::ConstEvaluatable(..) => {
                // Currently, we do not elaborate const-evaluatable
                // predicates.
            }
            ty::Predicate::RegionOutlives(..) => {
                // Nothing to elaborate from `'a: 'b`.
            }
            ty::Predicate::TypeOutlives(ref data) => {
                // We know that `T: 'a` for some type `T`. We can
                // often elaborate this. For example, if we know that
                // `[U]: 'a`, that implies that `U: 'a`. Similarly, if
                // we know `&'a U: 'b`, then we know that `'a: 'b` and
                // `U: 'b`.
                //
                // We can basically ignore bound regions here. So for
                // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to
                // `'a: 'b`.

                // Ignore `for<'a> T: 'a` -- we might in the future
                // consider this as evidence that `T: 'static`, but
                // I'm a bit wary of such constructions and so for now
                // I want to be conservative. --nmatsakis
                let ty_max = data.skip_binder().0;
                let r_min = data.skip_binder().1;
                if r_min.is_late_bound() {
                    return;
                }

                let visited = &mut self.visited;
                let mut components = smallvec![];
                tcx.push_outlives_components(ty_max, &mut components);
                self.stack.extend(
                    components
                        .into_iter()
                        .filter_map(|component| match component {
                            Component::Region(r) => if r.is_late_bound() {
                                None
                            } else {
                                Some(ty::Predicate::RegionOutlives(
                                    ty::Binder::dummy(ty::OutlivesPredicate(r, r_min))))
                            }

                            Component::Param(p) => {
                                let ty = tcx.mk_ty_param(p.index, p.name);
                                Some(ty::Predicate::TypeOutlives(
                                    ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min))))
                            }

                            Component::UnresolvedInferenceVariable(_) => {
                                None
                            }

                            Component::Projection(_) |
                            Component::EscapingProjection(_) => {
                                // We can probably do more here. This
                                // corresponds to a case like `<T as
                                // Foo<'a>>::U: 'b`.
                                None
                            }
                        })
                        .filter(|p| visited.insert(p))
                );
            }
        }
    }
}

impl Iterator for Elaborator<'tcx> {
    type Item = ty::Predicate<'tcx>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.stack.len(), None)
    }

    fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
        // Extract next item from top-most stack frame, if any.
        if let Some(pred) = self.stack.pop() {
            self.elaborate(&pred);
            Some(pred)
        } else {
            None
        }
    }
}

///////////////////////////////////////////////////////////////////////////
// Supertrait iterator
///////////////////////////////////////////////////////////////////////////

pub type Supertraits<'tcx> = FilterToTraits<Elaborator<'tcx>>;

pub fn supertraits<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_ref: ty::PolyTraitRef<'tcx>,
) -> Supertraits<'tcx> {
    elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
}

pub fn transitive_bounds<'tcx>(
    tcx: TyCtxt<'tcx>,
    bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
) -> Supertraits<'tcx> {
    elaborate_trait_refs(tcx, bounds).filter_to_traits()
}

///////////////////////////////////////////////////////////////////////////
// `TraitAliasExpander` iterator
///////////////////////////////////////////////////////////////////////////

/// "Trait alias expansion" is the process of expanding a sequence of trait
/// references into another sequence by transitively following all trait
/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias
/// `trait Foo = Bar + Sync;`, and another trait alias
/// `trait Bar = Read + Write`, then the bounds would expand to
/// `Read + Write + Sync + Send`.
/// Expansion is done via a DFS (depth-first search), and the `visited` field
/// is used to avoid cycles.
pub struct TraitAliasExpander<'tcx> {
    tcx: TyCtxt<'tcx>,
    stack: Vec<TraitAliasExpansionInfo<'tcx>>,
}

/// Stores information about the expansion of a trait via a path of zero or more trait aliases.
#[derive(Debug, Clone)]
pub struct TraitAliasExpansionInfo<'tcx> {
    pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>,
}

impl<'tcx> TraitAliasExpansionInfo<'tcx> {
    fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
        Self {
            path: smallvec![(trait_ref, span)]
        }
    }

    /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate
    /// trait aliases.
    pub fn label_with_exp_info(&self,
        diag: &mut DiagnosticBuilder<'_>,
        top_label: &str,
        use_desc: &str
    ) {
        diag.span_label(self.top().1, top_label);
        if self.path.len() > 1 {
            for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) {
                diag.span_label(*sp, format!("referenced here ({})", use_desc));
            }
        }
        diag.span_label(self.bottom().1,
            format!("trait alias used in trait object type ({})", use_desc));
    }

    pub fn trait_ref(&self) -> &ty::PolyTraitRef<'tcx> {
        &self.top().0
    }

    pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
        self.path.last().unwrap()
    }

    pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) {
        self.path.first().unwrap()
    }

    fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self {
        let mut path = self.path.clone();
        path.push((trait_ref, span));

        Self {
            path
        }
    }
}

pub fn expand_trait_aliases<'tcx>(
    tcx: TyCtxt<'tcx>,
    trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
) -> TraitAliasExpander<'tcx> {
    let items: Vec<_> = trait_refs
        .into_iter()
        .map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
        .collect();
    TraitAliasExpander { tcx, stack: items }
}

impl<'tcx> TraitAliasExpander<'tcx> {
    /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item`
    /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`.
    /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a
    /// trait alias.
    /// The return value indicates whether `item` should be yielded to the user.
    fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool {
        let tcx = self.tcx;
        let trait_ref = item.trait_ref();
        let pred = trait_ref.to_predicate();

        debug!("expand_trait_aliases: trait_ref={:?}", trait_ref);

        // Don't recurse if this bound is not a trait alias.
        let is_alias = tcx.is_trait_alias(trait_ref.def_id());
        if !is_alias {
            return true;
        }

        // Don't recurse if this trait alias is already on the stack for the DFS search.
        let anon_pred = anonymize_predicate(tcx, &pred);
        if item.path.iter().rev().skip(1)
                .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred) {
            return false;
        }

        // Get components of trait alias.
        let predicates = tcx.super_predicates_of(trait_ref.def_id());

        let items = predicates.predicates
            .iter()
            .rev()
            .filter_map(|(pred, span)| {
                pred.subst_supertrait(tcx, &trait_ref)
                    .to_opt_poly_trait_ref()
                    .map(|trait_ref| item.clone_and_push(trait_ref, *span))
            });
        debug!("expand_trait_aliases: items={:?}", items.clone());

        self.stack.extend(items);

        false
    }
}

impl<'tcx> Iterator for TraitAliasExpander<'tcx> {
    type Item = TraitAliasExpansionInfo<'tcx>;

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.stack.len(), None)
    }

    fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> {
        while let Some(item) = self.stack.pop() {
            if self.expand(&item) {
                return Some(item);
            }
        }
        None
    }
}

///////////////////////////////////////////////////////////////////////////
// Iterator over def-IDs of supertraits
///////////////////////////////////////////////////////////////////////////

pub struct SupertraitDefIds<'tcx> {
    tcx: TyCtxt<'tcx>,
    stack: Vec<DefId>,
    visited: FxHashSet<DefId>,
}

pub fn supertrait_def_ids(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SupertraitDefIds<'_> {
    SupertraitDefIds {
        tcx,
        stack: vec![trait_def_id],
        visited: Some(trait_def_id).into_iter().collect(),
    }
}

impl Iterator for SupertraitDefIds<'tcx> {
    type Item = DefId;

    fn next(&mut self) -> Option<DefId> {
        let def_id = self.stack.pop()?;
        let predicates = self.tcx.super_predicates_of(def_id);
        let visited = &mut self.visited;
        self.stack.extend(
            predicates.predicates
                      .iter()
                      .filter_map(|(pred, _)| pred.to_opt_poly_trait_ref())
                      .map(|trait_ref| trait_ref.def_id())
                      .filter(|&super_def_id| visited.insert(super_def_id)));
        Some(def_id)
    }
}

///////////////////////////////////////////////////////////////////////////
// Other
///////////////////////////////////////////////////////////////////////////

/// A filter around an iterator of predicates that makes it yield up
/// just trait references.
pub struct FilterToTraits<I> {
    base_iterator: I
}

impl<I> FilterToTraits<I> {
    fn new(base: I) -> FilterToTraits<I> {
        FilterToTraits { base_iterator: base }
    }
}

impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
    type Item = ty::PolyTraitRef<'tcx>;

    fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
        while let Some(pred) = self.base_iterator.next() {
            if let ty::Predicate::Trait(data) = pred {
                return Some(data.to_poly_trait_ref());
            }
        }
        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let (_, upper) = self.base_iterator.size_hint();
        (0, upper)
    }
}

///////////////////////////////////////////////////////////////////////////
// Other
///////////////////////////////////////////////////////////////////////////

/// Instantiate all bound parameters of the impl with the given substs,
/// returning the resulting trait ref and all obligations that arise.
/// The obligations are closed under normalization.
pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
    selcx: &mut SelectionContext<'a, 'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    impl_def_id: DefId,
    impl_substs: SubstsRef<'tcx>,
) -> (ty::TraitRef<'tcx>, Vec<PredicateObligation<'tcx>>) {
    let impl_trait_ref =
        selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
    let impl_trait_ref =
        impl_trait_ref.subst(selcx.tcx(), impl_substs);
    let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
        super::normalize(selcx, param_env, ObligationCause::dummy(), &impl_trait_ref);

    let predicates = selcx.tcx().predicates_of(impl_def_id);
    let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
    let Normalized { value: predicates, obligations: normalization_obligations2 } =
        super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
    let impl_obligations =
        predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);

    let impl_obligations: Vec<_> =
        impl_obligations.into_iter()
        .chain(normalization_obligations1)
        .chain(normalization_obligations2)
        .collect();

    (impl_trait_ref, impl_obligations)
}

/// See [`super::obligations_for_generics`].
pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
                                     recursion_depth: usize,
                                     param_env: ty::ParamEnv<'tcx>,
                                     generic_bounds: &ty::InstantiatedPredicates<'tcx>)
                                     -> Vec<PredicateObligation<'tcx>>
{
    debug!("predicates_for_generics(generic_bounds={:?})",
           generic_bounds);

    generic_bounds.predicates.iter().map(|predicate| {
        Obligation { cause: cause.clone(),
                     recursion_depth,
                     param_env,
                     predicate: predicate.clone() }
    }).collect()
}

pub fn predicate_for_trait_ref<'tcx>(
    cause: ObligationCause<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
    trait_ref: ty::TraitRef<'tcx>,
    recursion_depth: usize)
    -> PredicateObligation<'tcx>
{
    Obligation {
        cause,
        param_env,
        recursion_depth,
        predicate: trait_ref.to_predicate(),
    }
}

impl<'tcx> TyCtxt<'tcx> {
    pub fn predicate_for_trait_def(self,
                                   param_env: ty::ParamEnv<'tcx>,
                                   cause: ObligationCause<'tcx>,
                                   trait_def_id: DefId,
                                   recursion_depth: usize,
                                   self_ty: Ty<'tcx>,
                                   params: &[Kind<'tcx>])
        -> PredicateObligation<'tcx>
    {
        let trait_ref = ty::TraitRef {
            def_id: trait_def_id,
            substs: self.mk_substs_trait(self_ty, params)
        };
        predicate_for_trait_ref(cause, param_env, trait_ref, recursion_depth)
    }

    /// Casts a trait reference into a reference to one of its super
    /// traits; returns `None` if `target_trait_def_id` is not a
    /// supertrait.
    pub fn upcast_choices(self,
                          source_trait_ref: ty::PolyTraitRef<'tcx>,
                          target_trait_def_id: DefId)
                          -> Vec<ty::PolyTraitRef<'tcx>>
    {
        if source_trait_ref.def_id() == target_trait_def_id {
            return vec![source_trait_ref]; // Shortcut the most common case.
        }

        supertraits(self, source_trait_ref)
            .filter(|r| r.def_id() == target_trait_def_id)
            .collect()
    }

    /// Given a trait `trait_ref`, returns the number of vtable entries
    /// that come from `trait_ref`, excluding its supertraits. Used in
    /// computing the vtable base for an upcast trait of a trait object.
    pub fn count_own_vtable_entries(self, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
        let mut entries = 0;
        // Count number of methods and add them to the total offset.
        // Skip over associated types and constants.
        for trait_item in self.associated_items(trait_ref.def_id()) {
            if trait_item.kind == ty::AssocKind::Method {
                entries += 1;
            }
        }
        entries
    }

    /// Given an upcast trait object described by `object`, returns the
    /// index of the method `method_def_id` (which should be part of
    /// `object.upcast_trait_ref`) within the vtable for `object`.
    pub fn get_vtable_index_of_object_method<N>(self,
                                                object: &super::VtableObjectData<'tcx, N>,
                                                method_def_id: DefId) -> usize {
        // Count number of methods preceding the one we are selecting and
        // add them to the total offset.
        // Skip over associated types and constants.
        let mut entries = object.vtable_base;
        for trait_item in self.associated_items(object.upcast_trait_ref.def_id()) {
            if trait_item.def_id == method_def_id {
                // The item with the ID we were given really ought to be a method.
                assert_eq!(trait_item.kind, ty::AssocKind::Method);
                return entries;
            }
            if trait_item.kind == ty::AssocKind::Method {
                entries += 1;
            }
        }

        bug!("get_vtable_index_of_object_method: {:?} was not found",
             method_def_id);
    }

    pub fn closure_trait_ref_and_return_type(self,
        fn_trait_def_id: DefId,
        self_ty: Ty<'tcx>,
        sig: ty::PolyFnSig<'tcx>,
        tuple_arguments: TupleArgumentsFlag)
        -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>)>
    {
        let arguments_tuple = match tuple_arguments {
            TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
            TupleArgumentsFlag::Yes =>
                self.intern_tup(sig.skip_binder().inputs()),
        };
        let trait_ref = ty::TraitRef {
            def_id: fn_trait_def_id,
            substs: self.mk_substs_trait(self_ty, &[arguments_tuple.into()]),
        };
        ty::Binder::bind((trait_ref, sig.skip_binder().output()))
    }

    pub fn generator_trait_ref_and_outputs(self,
        fn_trait_def_id: DefId,
        self_ty: Ty<'tcx>,
        sig: ty::PolyGenSig<'tcx>)
        -> ty::Binder<(ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)>
    {
        let trait_ref = ty::TraitRef {
            def_id: fn_trait_def_id,
            substs: self.mk_substs_trait(self_ty, &[]),
        };
        ty::Binder::bind((trait_ref, sig.skip_binder().yield_ty, sig.skip_binder().return_ty))
    }

    pub fn impl_is_default(self, node_item_def_id: DefId) -> bool {
        match self.hir().as_local_hir_id(node_item_def_id) {
            Some(hir_id) => {
                let item = self.hir().expect_item(hir_id);
                if let hir::ItemKind::Impl(_, _, defaultness, ..) = item.node {
                    defaultness.is_default()
                } else {
                    false
                }
            }
            None => {
                self.global_tcx()
                    .impl_defaultness(node_item_def_id)
                    .is_default()
            }
        }
    }

    pub fn impl_item_is_final(self, node_item: &NodeItem<hir::Defaultness>) -> bool {
        node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id())
    }
}

pub enum TupleArgumentsFlag { Yes, No }
