use std::fmt::Debug;

use rustc_type_ir::inherent::*;
use rustc_type_ir::{
    self as ty, AliasTerm, Binder, FallibleTypeFolder, InferCtxtLike, Interner, TypeFoldable,
    TypeSuperFoldable, TypeVisitableExt, UniverseIndex, eager_resolve_vars,
};
use tracing::instrument;

use crate::placeholder::{BoundVarReplacer, PlaceholderReplacer};

/// This folder normalizes value and collects ambiguous goals.
///
/// Note that for ambiguous alias which contains escaping bound vars,
/// we just return the original alias and don't collect the ambiguous goal.
pub struct NormalizationFolder<'a, Infcx, I, F>
where
    Infcx: InferCtxtLike<Interner = I>,
    I: Interner,
{
    infcx: &'a Infcx,
    universes: Vec<Option<UniverseIndex>>,
    normalize: F,
}

#[derive(PartialEq, Eq)]
enum HasEscapingBoundVars {
    Yes,
    No,
}

#[derive(PartialEq, Eq)]
pub enum NormalizationWasAmbiguous {
    Yes,
    No,
}

impl<'a, Infcx, I, F, E> NormalizationFolder<'a, Infcx, I, F>
where
    Infcx: InferCtxtLike<Interner = I>,
    I: Interner,
    F: FnMut(AliasTerm<I>) -> Result<(I::Term, NormalizationWasAmbiguous), E>,
{
    pub fn new(infcx: &'a Infcx, universes: Vec<Option<UniverseIndex>>, normalize: F) -> Self {
        Self { infcx, universes, normalize }
    }

    fn normalize_alias_term(
        &mut self,
        alias_term: AliasTerm<I>,
        has_escaping: HasEscapingBoundVars,
    ) -> Result<Option<I::Term>, E> {
        let (normalized, normalization_was_ambiguous) = (self.normalize)(alias_term)?;

        // Return ambiguous higher ranked alias as is, if
        //   - it contains escaping vars, and
        //   - the normalized term contains infer vars which may mention
        //     temporary placeholders after we've already mapped them back
        //     to bound vars.
        //
        // We can normalize the ambiguous alias again after the binder is instantiated.
        if normalization_was_ambiguous == NormalizationWasAmbiguous::Yes
            && has_escaping == HasEscapingBoundVars::Yes
        {
            let max_universe = ty::max_universe_of_infer_vars(self.infcx, normalized);
            if max_universe.can_name(self.universes.first().unwrap().unwrap()) {
                return Ok(None);
            }
        }

        Ok(Some(normalized))
    }
}

impl<'a, Infcx, I, F, E> FallibleTypeFolder<I> for NormalizationFolder<'a, Infcx, I, F>
where
    Infcx: InferCtxtLike<Interner = I>,
    I: Interner,
    F: FnMut(AliasTerm<I>) -> Result<(I::Term, NormalizationWasAmbiguous), E>,
    E: Debug,
{
    type Error = E;

    fn cx(&self) -> I {
        self.infcx.cx()
    }

    fn try_fold_binder<T: TypeFoldable<I>>(
        &mut self,
        t: Binder<I, T>,
    ) -> Result<Binder<I, T>, Self::Error> {
        self.universes.push(None);
        let t = t.try_super_fold_with(self)?;
        self.universes.pop();
        Ok(t)
    }

    #[instrument(level = "trace", skip(self), ret)]
    fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Self::Error> {
        let infcx = self.infcx;
        let original = ty;

        if !self.cx().renormalize_rigid_aliases() && !ty.has_non_rigid_aliases() {
            return Ok(ty);
        }

        // With eager normalization, we should normalize the args of alias before
        // normalizing the alias itself.
        let ty = ty.try_super_fold_with(self)?;
        let ty::Alias(orig_is_rigid, alias_ty) = ty.kind() else { return Ok(ty) };
        // We support ambiguous aliases inside rigid alias. So we still recognize
        // the rigidness of the outer alias.
        if !self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes {
            return Ok(ty);
        }

        let normalized = if ty.has_escaping_bound_vars() {
            let (alias_ty, mapped_regions, mapped_types, mapped_consts) =
                BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, alias_ty);
            let Some(result) =
                self.normalize_alias_term(alias_ty.into(), HasEscapingBoundVars::Yes)?
            else {
                return Ok(ty);
            };

            PlaceholderReplacer::replace_placeholders(
                infcx,
                mapped_regions,
                mapped_types,
                mapped_consts,
                &self.universes,
                result.expect_ty(),
            )
        } else {
            self.normalize_alias_term(alias_ty.into(), HasEscapingBoundVars::No)?
                .map(|term| term.expect_ty())
                .unwrap_or(ty)
        };

        if self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes {
            // find out missing typing env change.
            let original = eager_resolve_vars(infcx, original);
            let normalized = eager_resolve_vars(infcx, normalized);
            assert_eq!(original, normalized, "rigid alias is further normalized");
        }
        Ok(normalized)
    }

    #[instrument(level = "trace", skip(self), ret)]
    fn try_fold_const(&mut self, ct: I::Const) -> Result<I::Const, Self::Error> {
        let infcx = self.infcx;
        let original = ct;

        if !self.cx().renormalize_rigid_aliases() && !ct.has_non_rigid_aliases() {
            return Ok(ct);
        }

        // With eager normalization, we should normalize the args of alias before
        // normalizing the alias itself.
        let ct = ct.try_super_fold_with(self)?;
        let ty::ConstKind::Alias(orig_is_rigid, alias_const) = ct.kind() else { return Ok(ct) };
        // We support ambiguous aliases inside rigid alias. So we still recognize
        // the rigidness of the outer alias.
        if !self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes {
            return Ok(ct);
        }

        let normalized = if ct.has_escaping_bound_vars() {
            let (alias_const, mapped_regions, mapped_types, mapped_consts) =
                BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, alias_const);
            let Some(result) =
                self.normalize_alias_term(alias_const.into(), HasEscapingBoundVars::Yes)?
            else {
                return Ok(ct);
            };
            PlaceholderReplacer::replace_placeholders(
                infcx,
                mapped_regions,
                mapped_types,
                mapped_consts,
                &self.universes,
                result.expect_const(),
            )
        } else {
            self.normalize_alias_term(alias_const.into(), HasEscapingBoundVars::No)?
                .map(|term| term.expect_const())
                .unwrap_or(ct)
        };

        if self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes {
            // find out missing typing env change.
            let original = eager_resolve_vars(infcx, original);
            let normalized = eager_resolve_vars(infcx, normalized);
            assert_eq!(original, normalized, "rigid alias is further normalized");
        }

        Ok(normalized)
    }

    fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error> {
        if p.allow_normalization() { p.try_super_fold_with(self) } else { Ok(p) }
    }
}
