use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
use std::iter;

pub(crate) fn provide(providers: &mut Providers) {
    *providers = Providers {
        assumed_wf_types,
        assumed_wf_types_for_rpitit: |tcx, def_id| {
            assert!(tcx.is_impl_trait_in_trait(def_id.to_def_id()));
            tcx.assumed_wf_types(def_id)
        },
        ..*providers
    };
}

fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
    match tcx.def_kind(def_id) {
        DefKind::Fn => {
            let sig = tcx.fn_sig(def_id).instantiate_identity();
            let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
            tcx.arena.alloc_from_iter(itertools::zip_eq(
                liberated_sig.inputs_and_output,
                fn_sig_spans(tcx, def_id),
            ))
        }
        DefKind::AssocFn => {
            let sig = tcx.fn_sig(def_id).instantiate_identity();
            let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
            let mut assumed_wf_types: Vec<_> =
                tcx.assumed_wf_types(tcx.local_parent(def_id)).into();
            assumed_wf_types.extend(itertools::zip_eq(
                liberated_sig.inputs_and_output,
                fn_sig_spans(tcx, def_id),
            ));
            tcx.arena.alloc_slice(&assumed_wf_types)
        }
        DefKind::Impl { .. } => {
            // Trait arguments and the self type for trait impls or only the self type for
            // inherent impls.
            let tys = match tcx.impl_trait_ref(def_id) {
                Some(trait_ref) => trait_ref.skip_binder().args.types().collect(),
                None => vec![tcx.type_of(def_id).instantiate_identity()],
            };

            let mut impl_spans = impl_spans(tcx, def_id);
            tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
        }
        DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => {
            match data {
                ty::ImplTraitInTraitData::Trait { fn_def_id, .. } => {
                    // We need to remap all of the late-bound lifetimes in the assumed wf types
                    // of the fn (which are represented as ReLateParam) to the early-bound lifetimes
                    // of the RPITIT (which are represented by ReEarlyParam owned by the opaque).
                    // Luckily, this is very easy to do because we already have that mapping
                    // stored in the HIR of this RPITIT.
                    //
                    // Side-note: We don't really need to do this remapping for early-bound
                    // lifetimes because they're already "linked" by the bidirectional outlives
                    // predicates we insert in the `explicit_predicates_of` query for RPITITs.
                    let mut mapping = FxHashMap::default();
                    let generics = tcx.generics_of(def_id);

                    // For each captured opaque lifetime, if it's late-bound (`ReLateParam` in this
                    // case, since it has been liberated), map it back to the early-bound lifetime of
                    // the GAT. Since RPITITs also have all of the fn's generics, we slice only
                    // the end of the list corresponding to the opaque's generics.
                    for param in &generics.own_params[tcx.generics_of(fn_def_id).own_params.len()..]
                    {
                        let orig_lt =
                            tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
                        if matches!(*orig_lt, ty::ReLateParam(..)) {
                            mapping.insert(
                                orig_lt,
                                ty::Region::new_early_param(
                                    tcx,
                                    ty::EarlyParamRegion {
                                        def_id: param.def_id,
                                        index: param.index,
                                        name: param.name,
                                    },
                                ),
                            );
                        }
                    }
                    // FIXME: This could use a real folder, I guess.
                    let remapped_wf_tys = tcx.fold_regions(
                        tcx.assumed_wf_types(fn_def_id.expect_local()).to_vec(),
                        |region, _| {
                            // If `region` is a `ReLateParam` that is captured by the
                            // opaque, remap it to its corresponding the early-
                            // bound region.
                            if let Some(remapped_region) = mapping.get(&region) {
                                *remapped_region
                            } else {
                                region
                            }
                        },
                    );
                    tcx.arena.alloc_from_iter(remapped_wf_tys)
                }
                // Assumed wf types for RPITITs in an impl just inherit (and instantiate)
                // the assumed wf types of the trait's RPITIT GAT.
                ty::ImplTraitInTraitData::Impl { .. } => {
                    let impl_def_id = tcx.local_parent(def_id);
                    let rpitit_def_id = tcx.associated_item(def_id).trait_item_def_id.unwrap();
                    let args = ty::GenericArgs::identity_for_item(tcx, def_id).rebase_onto(
                        tcx,
                        impl_def_id.to_def_id(),
                        tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args,
                    );
                    tcx.arena.alloc_from_iter(
                        ty::EarlyBinder::bind(tcx.assumed_wf_types_for_rpitit(rpitit_def_id))
                            .iter_instantiated_copied(tcx, args)
                            .chain(tcx.assumed_wf_types(impl_def_id).into_iter().copied()),
                    )
                }
            }
        }
        DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
        DefKind::OpaqueTy => bug!("implied bounds are not defined for opaques"),
        DefKind::Mod
        | DefKind::Struct
        | DefKind::Union
        | DefKind::Enum
        | DefKind::Variant
        | DefKind::Trait
        | DefKind::TyAlias
        | DefKind::ForeignTy
        | DefKind::TraitAlias
        | DefKind::TyParam
        | DefKind::Const
        | DefKind::ConstParam
        | DefKind::Static { .. }
        | DefKind::Ctor(_, _)
        | DefKind::Macro(_)
        | DefKind::ExternCrate
        | DefKind::Use
        | DefKind::ForeignMod
        | DefKind::AnonConst
        | DefKind::InlineConst
        | DefKind::Field
        | DefKind::LifetimeParam
        | DefKind::GlobalAsm
        | DefKind::Closure => ty::List::empty(),
    }
}

fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
    let node = tcx.hir_node_by_def_id(def_id);
    if let Some(decl) = node.fn_decl() {
        decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span()))
    } else {
        bug!("unexpected item for fn {def_id:?}: {node:?}")
    }
}

fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
    let item = tcx.hir().expect_item(def_id);
    if let hir::ItemKind::Impl(impl_) = item.kind {
        let trait_args = impl_
            .of_trait
            .into_iter()
            .flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args)
            .map(|arg| arg.span());
        let dummy_spans_for_default_args =
            impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span));
        iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args)
    } else {
        bug!("unexpected item for impl {def_id:?}: {item:?}")
    }
}
