mod render;

#[cfg(test)]
mod tests;

use std::{iter, ops::Not};

use either::Either;
use hir::{
    DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics,
};
use ide_db::{
    FileRange, FxIndexSet, MiniCore, Ranker, RootDatabase,
    defs::{Definition, IdentClass, NameRefClass, OperatorClass},
    famous_defs::FamousDefs,
    helpers::pick_best_token,
    ra_fixture::UpmapFromRaFixture,
};
use itertools::{Itertools, multizip};
use macros::UpmapFromRaFixture;
use span::{Edition, TextRange};
use syntax::{
    AstNode, AstToken,
    SyntaxKind::{self, *},
    SyntaxNode, T, ast,
};

use crate::{
    Analysis, FileId, FilePosition, NavigationTarget, RangeInfo, Runnable, TryToNav,
    doc_links::token_as_doc_comment,
    markdown_remove::remove_markdown,
    markup::Markup,
    navigation_target::UpmappingResult,
    runnables::{runnable_fn, runnable_mod},
};

#[derive(Clone, Debug)]
pub struct HoverConfig<'a> {
    pub links_in_hover: bool,
    pub memory_layout: Option<MemoryLayoutHoverConfig>,
    pub documentation: bool,
    pub keywords: bool,
    pub format: HoverDocFormat,
    pub max_trait_assoc_items_count: Option<usize>,
    pub max_fields_count: Option<usize>,
    pub max_enum_variants_count: Option<usize>,
    pub max_subst_ty_len: SubstTyLen,
    pub show_drop_glue: bool,
    pub minicore: MiniCore<'a>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SubstTyLen {
    Unlimited,
    LimitTo(usize),
    Hide,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MemoryLayoutHoverConfig {
    pub size: Option<MemoryLayoutHoverRenderKind>,
    pub offset: Option<MemoryLayoutHoverRenderKind>,
    pub alignment: Option<MemoryLayoutHoverRenderKind>,
    pub padding: Option<MemoryLayoutHoverRenderKind>,
    pub niches: bool,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum MemoryLayoutHoverRenderKind {
    Decimal,
    Hexadecimal,
    Both,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum HoverDocFormat {
    Markdown,
    PlainText,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, UpmapFromRaFixture)]
pub enum HoverAction {
    Runnable(Runnable),
    Implementation(FilePosition),
    Reference(FilePosition),
    GoToType(Vec<HoverGotoTypeData>),
}

impl HoverAction {
    fn goto_type_from_targets(
        sema: &Semantics<'_, RootDatabase>,
        targets: Vec<hir::ModuleDef>,
        edition: Edition,
    ) -> Option<Self> {
        let db = sema.db;
        let targets = targets
            .into_iter()
            .filter_map(|it| {
                Some(HoverGotoTypeData {
                    mod_path: render::path(
                        db,
                        it.module(db)?,
                        it.name(db).map(|name| name.display(db, edition).to_string()),
                        edition,
                    ),
                    nav: it.try_to_nav(sema)?.call_site(),
                })
            })
            .collect::<Vec<_>>();
        targets.is_empty().not().then_some(HoverAction::GoToType(targets))
    }
}

#[derive(Debug, Clone, Eq, PartialEq, Hash, UpmapFromRaFixture)]
pub struct HoverGotoTypeData {
    pub mod_path: String,
    pub nav: NavigationTarget,
}

/// Contains the results when hovering over an item
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, UpmapFromRaFixture)]
pub struct HoverResult {
    pub markup: Markup,
    pub actions: Vec<HoverAction>,
}

// Feature: Hover
//
// Shows additional information, like the type of an expression or the documentation for a definition when "focusing" code.
// Focusing is usually hovering with a mouse, but can also be triggered with a shortcut.
//
// ![Hover](https://user-images.githubusercontent.com/48062697/113020658-b5f98b80-917a-11eb-9f88-3dbc27320c95.gif)
pub(crate) fn hover(
    db: &RootDatabase,
    frange @ FileRange { file_id, range }: FileRange,
    config: &HoverConfig<'_>,
) -> Option<RangeInfo<HoverResult>> {
    let sema = &hir::Semantics::new(db);
    let file = sema.parse_guess_edition(file_id).syntax().clone();
    let edition =
        sema.attach_first_edition(file_id).map(|it| it.edition(db)).unwrap_or(Edition::CURRENT);
    let display_target = sema.first_crate(file_id)?.to_display_target(db);
    let mut res = if range.is_empty() {
        hover_offset(
            sema,
            FilePosition { file_id, offset: range.start() },
            file,
            config,
            edition,
            display_target,
        )
    } else {
        hover_ranged(sema, frange, file, config, edition, display_target)
    }?;

    if let HoverDocFormat::PlainText = config.format {
        res.info.markup = remove_markdown(res.info.markup.as_str()).into();
    }
    Some(res)
}

#[allow(clippy::field_reassign_with_default)]
fn hover_offset(
    sema: &Semantics<'_, RootDatabase>,
    FilePosition { file_id, offset }: FilePosition,
    file: SyntaxNode,
    config: &HoverConfig<'_>,
    edition: Edition,
    display_target: DisplayTarget,
) -> Option<RangeInfo<HoverResult>> {
    let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
        IDENT
        | INT_NUMBER
        | LIFETIME_IDENT
        | T![self]
        | T![super]
        | T![crate]
        | T![Self]
        | T![_] => 4,
        // index and prefix ops and closure pipe
        T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] | T![|] => 3,
        kind if kind.is_keyword(edition) => 2,
        T!['('] | T![')'] => 2,
        kind if kind.is_trivia() => 0,
        _ => 1,
    })?;

    if let Some(doc_comment) = token_as_doc_comment(&original_token) {
        cov_mark::hit!(no_highlight_on_comment_hover);
        return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
            let res = hover_for_definition(
                sema,
                file_id,
                def,
                None,
                &node,
                None,
                false,
                config,
                edition,
                display_target,
            );
            Some(RangeInfo::new(range, res))
        });
    }

    if let Some((range, _, _, resolution)) =
        sema.check_for_format_args_template(original_token.clone(), offset)
    {
        let res = hover_for_definition(
            sema,
            file_id,
            Definition::from(resolution?),
            None,
            &original_token.parent()?,
            None,
            false,
            config,
            edition,
            display_target,
        );
        return Some(RangeInfo::new(range, res));
    }

    if let Some(literal) = ast::String::cast(original_token.clone())
        && let Some((analysis, fixture_analysis)) =
            Analysis::from_ra_fixture(sema, literal.clone(), &literal, config.minicore)
    {
        let (virtual_file_id, virtual_offset) = fixture_analysis.map_offset_down(offset)?;
        return analysis
            .hover(
                config,
                FileRange { file_id: virtual_file_id, range: TextRange::empty(virtual_offset) },
            )
            .ok()??
            .upmap_from_ra_fixture(&fixture_analysis, virtual_file_id, file_id)
            .ok();
    }

    // prefer descending the same token kind in attribute expansions, in normal macros text
    // equivalency is more important
    let mut descended = sema.descend_into_macros(original_token.clone());

    let ranker = Ranker::from_token(&original_token);

    descended.sort_by_cached_key(|tok| !ranker.rank_token(tok));

    let mut res = vec![];
    for token in descended {
        let is_same_kind = token.kind() == ranker.kind;
        let lint_hover = (|| {
            // FIXME: Definition should include known lints and the like instead of having this special case here
            let attr = token.parent_ancestors().find_map(ast::Attr::cast)?;
            render::try_for_lint(&attr, &token)
        })();
        if let Some(lint_hover) = lint_hover {
            res.push(lint_hover);
            continue;
        }
        let definitions = (|| {
            Some(
                'a: {
                    let node = token.parent()?;

                    // special case macro calls, we wanna render the invoked arm index
                    if let Some(name) = ast::NameRef::cast(node.clone())
                        && let Some(path_seg) =
                            name.syntax().parent().and_then(ast::PathSegment::cast)
                            && let Some(macro_call) = path_seg
                                .parent_path()
                                .syntax()
                                .parent()
                                .and_then(ast::MacroCall::cast)
                                && let Some(macro_) = sema.resolve_macro_call(&macro_call) {
                                    break 'a vec![(
                                        (Definition::Macro(macro_), None),
                                        sema.resolve_macro_call_arm(&macro_call),
                                        false,
                                        node,
                                    )];
                                }

                    match IdentClass::classify_node(sema, &node)? {
                        // It's better for us to fall back to the keyword hover here,
                        // rendering poll is very confusing
                        IdentClass::Operator(OperatorClass::Await(_)) => return None,

                        IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand {
                            decl,
                            ..
                        }) => {
                            vec![((Definition::ExternCrateDecl(decl), None), None, false, node)]
                        }

                        class => {
                            let render_extras = matches!(class, IdentClass::NameClass(_))
                                // Render extra information for `Self` keyword as well
                                || ast::NameRef::cast(node.clone()).is_some_and(|name_ref| name_ref.token_kind() == SyntaxKind::SELF_TYPE_KW);
                            multizip((
                                class.definitions(),
                                iter::repeat(None),
                                iter::repeat(render_extras),
                                iter::repeat(node),
                            ))
                            .collect::<Vec<_>>()
                        }
                    }
                }
                .into_iter()
                .unique_by(|&((def, _), _, _, _)| def)
                .map(|((def, subst), macro_arm, hovered_definition, node)| {
                    hover_for_definition(
                        sema,
                        file_id,
                        def,
                        subst,
                        &node,
                        macro_arm,
                        hovered_definition,
                        config,
                        edition,
                        display_target,
                    )
                })
                .collect::<Vec<_>>(),
            )
        })();
        if let Some(definitions) = definitions {
            res.extend(definitions);
            continue;
        }
        let keywords = || render::keyword(sema, config, &token, edition, display_target);
        let underscore = || {
            if !is_same_kind {
                return None;
            }
            render::underscore(sema, config, &token, edition, display_target)
        };
        let rest_pat = || {
            if !is_same_kind || token.kind() != DOT2 {
                return None;
            }

            let rest_pat = token.parent().and_then(ast::RestPat::cast)?;
            let record_pat_field_list =
                rest_pat.syntax().parent().and_then(ast::RecordPatFieldList::cast)?;

            let record_pat =
                record_pat_field_list.syntax().parent().and_then(ast::RecordPat::cast)?;

            Some(render::struct_rest_pat(sema, config, &record_pat, edition, display_target))
        };
        let call = || {
            if !is_same_kind || token.kind() != T!['('] && token.kind() != T![')'] {
                return None;
            }
            let arg_list = token.parent().and_then(ast::ArgList::cast)?.syntax().parent()?;
            let call_expr = syntax::match_ast! {
                match arg_list {
                    ast::CallExpr(expr) => expr.into(),
                    ast::MethodCallExpr(expr) => expr.into(),
                    _ => return None,
                }
            };
            render::type_info_of(sema, config, &Either::Left(call_expr), edition, display_target)
        };
        let closure = || {
            if !is_same_kind || token.kind() != T![|] {
                return None;
            }
            let c = token.parent().and_then(|x| x.parent()).and_then(ast::ClosureExpr::cast)?;
            render::closure_expr(sema, config, c, edition, display_target)
        };
        let literal = || {
            render::literal(sema, original_token.clone(), display_target)
                .map(|markup| HoverResult { markup, actions: vec![] })
        };
        if let Some(result) = keywords()
            .or_else(underscore)
            .or_else(rest_pat)
            .or_else(call)
            .or_else(closure)
            .or_else(literal)
        {
            res.push(result)
        }
    }

    res.into_iter()
        .unique()
        .reduce(|mut acc: HoverResult, HoverResult { markup, actions }| {
            acc.actions.extend(actions);
            acc.markup = Markup::from(format!("{}\n\n---\n{markup}", acc.markup));
            acc
        })
        .map(|mut res: HoverResult| {
            res.actions = dedupe_or_merge_hover_actions(res.actions);
            RangeInfo::new(original_token.text_range(), res)
        })
}

fn hover_ranged(
    sema: &Semantics<'_, RootDatabase>,
    FileRange { file_id, range }: FileRange,
    file: SyntaxNode,
    config: &HoverConfig<'_>,
    edition: Edition,
    display_target: DisplayTarget,
) -> Option<RangeInfo<HoverResult>> {
    // FIXME: make this work in attributes
    let expr_or_pat = file
        .covering_element(range)
        .ancestors()
        .take_while(|it| ast::MacroCall::can_cast(it.kind()) || !ast::Item::can_cast(it.kind()))
        .find_map(Either::<ast::Expr, ast::Pat>::cast)?;
    let res = match &expr_or_pat {
        Either::Left(ast::Expr::TryExpr(try_expr)) => {
            render::try_expr(sema, config, try_expr, edition, display_target)
        }
        Either::Left(ast::Expr::PrefixExpr(prefix_expr))
            if prefix_expr.op_kind() == Some(ast::UnaryOp::Deref) =>
        {
            render::deref_expr(sema, config, prefix_expr, edition, display_target)
        }
        Either::Left(ast::Expr::Literal(literal)) => {
            if let Some(literal) = ast::String::cast(literal.token())
                && let Some((analysis, fixture_analysis)) =
                    Analysis::from_ra_fixture(sema, literal.clone(), &literal, config.minicore)
            {
                let (virtual_file_id, virtual_range) = fixture_analysis.map_range_down(range)?;
                return analysis
                    .hover(config, FileRange { file_id: virtual_file_id, range: virtual_range })
                    .ok()??
                    .upmap_from_ra_fixture(&fixture_analysis, virtual_file_id, file_id)
                    .ok();
            }
            None
        }
        _ => None,
    };
    let res =
        res.or_else(|| render::type_info_of(sema, config, &expr_or_pat, edition, display_target));
    res.map(|it| {
        let range = match expr_or_pat {
            Either::Left(it) => it.syntax().text_range(),
            Either::Right(it) => it.syntax().text_range(),
        };
        RangeInfo::new(range, it)
    })
}

// FIXME: Why is this pub(crate)?
pub(crate) fn hover_for_definition(
    sema: &Semantics<'_, RootDatabase>,
    file_id: FileId,
    def: Definition,
    subst: Option<GenericSubstitution<'_>>,
    scope_node: &SyntaxNode,
    macro_arm: Option<u32>,
    render_extras: bool,
    config: &HoverConfig<'_>,
    edition: Edition,
    display_target: DisplayTarget,
) -> HoverResult {
    let famous_defs = match &def {
        Definition::BuiltinType(_) => sema.scope(scope_node).map(|it| FamousDefs(sema, it.krate())),
        _ => None,
    };

    let db = sema.db;
    let def_ty = match def {
        Definition::Local(it) => Some(it.ty(db)),
        Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)),
        Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)),
        Definition::Field(field) => Some(field.ty(db).to_type(db)),
        Definition::TupleField(it) => Some(it.ty(db)),
        Definition::Function(it) => Some(it.ty(db)),
        Definition::Adt(it) => Some(it.ty(db)),
        Definition::Const(it) => Some(it.ty(db)),
        Definition::Static(it) => Some(it.ty(db)),
        Definition::TypeAlias(it) => Some(it.ty(db)),
        Definition::BuiltinType(it) => Some(it.ty(db)),
        _ => None,
    };
    let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
    let subst_types = subst.map(|subst| subst.types(db));

    let (markup, range_map) = render::definition(
        sema.db,
        def,
        famous_defs.as_ref(),
        &notable_traits,
        macro_arm,
        render_extras,
        subst_types.as_ref(),
        config,
        edition,
        display_target,
    );
    HoverResult {
        markup: render::process_markup(sema.db, def, &markup, range_map, config),
        actions: [
            show_fn_references_action(sema, def),
            show_implementations_action(sema, def),
            runnable_action(sema, def, file_id),
            goto_type_action_for_def(sema, def, &notable_traits, subst_types, edition),
        ]
        .into_iter()
        .flatten()
        .collect(),
    }
}

fn notable_traits<'db>(
    db: &'db RootDatabase,
    ty: &hir::Type<'db>,
) -> Vec<(hir::Trait, Vec<(Option<hir::Type<'db>>, hir::Name)>)> {
    if ty.is_unknown() {
        // The trait solver returns "yes" to the question whether the error type
        // impls any trait, and we don't want to show it as having any notable trait.
        return Vec::new();
    }

    ty.krate(db)
        .notable_traits_in_deps(db)
        .filter_map(move |&trait_| {
            let trait_ = trait_.into();
            ty.impls_trait(db, trait_, &[]).then(|| {
                (
                    trait_,
                    trait_
                        .items(db)
                        .into_iter()
                        .filter_map(hir::AssocItem::as_type_alias)
                        .map(|alias| {
                            (ty.normalize_trait_assoc_type(db, &[], alias), alias.name(db))
                        })
                        .collect::<Vec<_>>(),
                )
            })
        })
        .sorted_by_cached_key(|(trait_, _)| trait_.name(db))
        .collect::<Vec<_>>()
}

fn show_implementations_action(
    sema: &Semantics<'_, RootDatabase>,
    def: Definition,
) -> Option<HoverAction> {
    fn to_action(nav_target: NavigationTarget) -> HoverAction {
        HoverAction::Implementation(FilePosition {
            file_id: nav_target.file_id,
            offset: nav_target.focus_or_full_range().start(),
        })
    }

    let adt = match def {
        Definition::Trait(it) => {
            return it.try_to_nav(sema).map(UpmappingResult::call_site).map(to_action);
        }
        Definition::Adt(it) => Some(it),
        Definition::SelfType(it) => it.self_ty(sema.db).as_adt(),
        _ => None,
    }?;
    adt.try_to_nav(sema).map(UpmappingResult::call_site).map(to_action)
}

fn show_fn_references_action(
    sema: &Semantics<'_, RootDatabase>,
    def: Definition,
) -> Option<HoverAction> {
    match def {
        Definition::Function(it) => {
            it.try_to_nav(sema).map(UpmappingResult::call_site).map(|nav_target| {
                HoverAction::Reference(FilePosition {
                    file_id: nav_target.file_id,
                    offset: nav_target.focus_or_full_range().start(),
                })
            })
        }
        _ => None,
    }
}

fn runnable_action(
    sema: &hir::Semantics<'_, RootDatabase>,
    def: Definition,
    file_id: FileId,
) -> Option<HoverAction> {
    match def {
        Definition::Module(it) => runnable_mod(sema, it).map(HoverAction::Runnable),
        Definition::Function(func) => {
            let src = func.source(sema.db)?;
            if src.file_id.file_id().is_none_or(|f| f.file_id(sema.db) != file_id) {
                cov_mark::hit!(hover_macro_generated_struct_fn_doc_comment);
                cov_mark::hit!(hover_macro_generated_struct_fn_doc_attr);
                return None;
            }

            runnable_fn(sema, func).map(HoverAction::Runnable)
        }
        _ => None,
    }
}

fn goto_type_action_for_def(
    sema: &Semantics<'_, RootDatabase>,
    def: Definition,
    notable_traits: &[(hir::Trait, Vec<(Option<hir::Type<'_>>, hir::Name)>)],
    subst_types: Option<Vec<(hir::Symbol, hir::Type<'_>)>>,
    edition: Edition,
) -> Option<HoverAction> {
    let db = sema.db;
    let mut targets: Vec<hir::ModuleDef> = Vec::new();
    let mut push_new_def = |item: hir::ModuleDef| {
        if !targets.contains(&item) {
            targets.push(item);
        }
    };

    for &(trait_, ref assocs) in notable_traits {
        push_new_def(trait_.into());
        assocs.iter().filter_map(|(ty, _)| ty.as_ref()).for_each(|ty| {
            walk_and_push_ty(db, ty, &mut push_new_def);
        });
    }

    if let Ok(generic_def) = GenericDef::try_from(def) {
        generic_def.type_or_const_params(db).into_iter().for_each(|it| {
            walk_and_push_ty(db, &it.ty(db), &mut push_new_def);
        });
    }

    let ty = match def {
        Definition::Local(it) => Some(it.ty(db)),
        Definition::Field(field) => Some(field.ty(db).to_type(db)),
        Definition::TupleField(field) => Some(field.ty(db)),
        Definition::Const(it) => Some(it.ty(db)),
        Definition::Static(it) => Some(it.ty(db)),
        Definition::Function(func) => {
            for param in func.assoc_fn_params(db) {
                walk_and_push_ty(db, param.ty(), &mut push_new_def);
            }
            Some(func.ret_type(db))
        }
        Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)),
        Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)),
        _ => None,
    };
    if let Some(ty) = ty {
        walk_and_push_ty(db, &ty, &mut push_new_def);
    }

    if let Some(subst_types) = subst_types {
        for (_, ty) in subst_types {
            walk_and_push_ty(db, &ty, &mut push_new_def);
        }
    }

    HoverAction::goto_type_from_targets(sema, targets, edition)
}

fn walk_and_push_ty(
    db: &RootDatabase,
    ty: &hir::Type<'_>,
    push_new_def: &mut dyn FnMut(hir::ModuleDef),
) {
    ty.walk(db, |t| {
        if let Some(adt) = t.as_adt() {
            push_new_def(adt.into());
        } else if let Some(trait_) = t.as_dyn_trait() {
            push_new_def(trait_.into());
        } else if let Some(traits) = t.as_impl_traits(db) {
            traits.for_each(|it| push_new_def(it.into()));
        } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
            push_new_def(trait_.into());
        } else if let Some(tp) = t.as_type_param(db) {
            let sized_trait = LangItem::Sized.resolve_trait(db, t.krate(db).into());
            tp.trait_bounds(db)
                .into_iter()
                .filter(|&it| Some(it.into()) != sized_trait)
                .for_each(|it| push_new_def(it.into()));
        }
    });
}

fn dedupe_or_merge_hover_actions(actions: Vec<HoverAction>) -> Vec<HoverAction> {
    let mut deduped_actions = Vec::with_capacity(actions.len());
    let mut go_to_type_targets = FxIndexSet::default();

    let mut seen_implementation = false;
    let mut seen_reference = false;
    let mut seen_runnable = false;
    for action in actions {
        match action {
            HoverAction::GoToType(targets) => {
                go_to_type_targets.extend(targets);
            }
            HoverAction::Implementation(..) => {
                if !seen_implementation {
                    seen_implementation = true;
                    deduped_actions.push(action);
                }
            }
            HoverAction::Reference(..) => {
                if !seen_reference {
                    seen_reference = true;
                    deduped_actions.push(action);
                }
            }
            HoverAction::Runnable(..) => {
                if !seen_runnable {
                    seen_runnable = true;
                    deduped_actions.push(action);
                }
            }
        };
    }

    if !go_to_type_targets.is_empty() {
        deduped_actions.push(HoverAction::GoToType(
            go_to_type_targets.into_iter().sorted_by(|a, b| a.mod_path.cmp(&b.mod_path)).collect(),
        ));
    }

    deduped_actions
}
