//! This module defines an accumulator for completions which are going to be presented to user.

pub(crate) mod attribute;
pub(crate) mod dot;
pub(crate) mod env_vars;
pub(crate) mod expr;
pub(crate) mod extern_abi;
pub(crate) mod extern_crate;
pub(crate) mod field;
pub(crate) mod flyimport;
pub(crate) mod fn_param;
pub(crate) mod format_string;
pub(crate) mod item_list;
pub(crate) mod keyword;
pub(crate) mod lifetime;
pub(crate) mod mod_;
pub(crate) mod pattern;
pub(crate) mod postfix;
pub(crate) mod record;
pub(crate) mod snippet;
pub(crate) mod r#type;
pub(crate) mod use_;
pub(crate) mod vis;

use std::iter;

use hir::{HasAttrs, Name, ScopeDef, Variant, sym};
use ide_db::{RootDatabase, SymbolKind, imports::import_assets::LocatedImport};
use syntax::{SmolStr, ToSmolStr, ast};

use crate::{
    CompletionContext, CompletionItem, CompletionItemKind,
    context::{
        DotAccess, ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind,
        PathCompletionCtx, PathKind, PatternContext, TypeLocation, Visible,
    },
    item::Builder,
    render::{
        RenderContext,
        const_::render_const,
        function::{render_fn, render_method},
        literal::{render_struct_literal, render_variant_lit},
        macro_::render_macro,
        pattern::{render_struct_pat, render_variant_pat},
        render_expr, render_field, render_path_resolution, render_pattern_resolution,
        render_tuple_field,
        type_alias::{render_type_alias, render_type_alias_with_eq},
        union_literal::render_union_literal,
    },
};

/// Represents an in-progress set of completions being built.
#[derive(Debug, Default)]
pub struct Completions {
    buf: Vec<CompletionItem>,
}

impl From<Completions> for Vec<CompletionItem> {
    fn from(val: Completions) -> Self {
        val.buf
    }
}

impl Builder {
    /// Convenience method, which allows to add a freshly created completion into accumulator
    /// without binding it to the variable.
    pub(crate) fn add_to(self, acc: &mut Completions, db: &RootDatabase) {
        acc.add(self.build(db))
    }
}

impl Completions {
    fn add(&mut self, item: CompletionItem) {
        self.buf.push(item)
    }

    fn add_opt(&mut self, item: Option<CompletionItem>) {
        if let Some(item) = item {
            self.buf.push(item)
        }
    }

    pub(crate) fn add_keyword(&mut self, ctx: &CompletionContext<'_>, keyword: &'static str) {
        let item = CompletionItem::new(
            CompletionItemKind::Keyword,
            ctx.source_range(),
            SmolStr::new_static(keyword),
            ctx.edition,
        );
        item.add_to(self, ctx.db);
    }

    pub(crate) fn add_nameref_keywords_with_colon(&mut self, ctx: &CompletionContext<'_>) {
        ["self::", "crate::"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));

        if ctx.depth_from_crate_root > 0 {
            self.add_keyword(ctx, "super::");
        }
    }

    pub(crate) fn add_nameref_keywords(&mut self, ctx: &CompletionContext<'_>) {
        ["self", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));

        if ctx.depth_from_crate_root > 0 {
            self.add_keyword(ctx, "super");
        }
    }

    pub(crate) fn add_super_keyword(
        &mut self,
        ctx: &CompletionContext<'_>,
        super_chain_len: Option<usize>,
    ) {
        if let Some(len) = super_chain_len
            && len > 0
            && len < ctx.depth_from_crate_root
        {
            self.add_keyword(ctx, "super::");
        }
    }

    pub(crate) fn add_keyword_snippet_expr(
        &mut self,
        ctx: &CompletionContext<'_>,
        incomplete_let: bool,
        kw: &str,
        snippet: &str,
    ) {
        let mut item =
            CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw, ctx.edition);

        match ctx.config.snippet_cap {
            Some(cap) => {
                if incomplete_let && snippet.ends_with('}') {
                    // complete block expression snippets with a trailing semicolon, if inside an incomplete let
                    cov_mark::hit!(let_semi);
                    item.insert_snippet(cap, format!("{snippet};"));
                } else {
                    item.insert_snippet(cap, snippet);
                }
            }
            None => {
                item.insert_text(if snippet.contains('$') { kw } else { snippet });
            }
        };
        item.add_to(self, ctx.db);
    }

    pub(crate) fn add_keyword_snippet(
        &mut self,
        ctx: &CompletionContext<'_>,
        kw: &str,
        snippet: &str,
    ) {
        let mut item =
            CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw, ctx.edition);

        match ctx.config.snippet_cap {
            Some(cap) => item.insert_snippet(cap, snippet),
            None => item.insert_text(if snippet.contains('$') { kw } else { snippet }),
        };
        item.add_to(self, ctx.db);
    }

    pub(crate) fn add_expr(
        &mut self,
        ctx: &CompletionContext<'_>,
        expr: &hir::term_search::Expr<'_>,
    ) {
        if let Some(item) = render_expr(ctx, expr) {
            item.add_to(self, ctx.db)
        }
    }

    pub(crate) fn add_crate_roots(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
    ) {
        ctx.process_all_names(&mut |name, res, doc_aliases| match res {
            ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root() => {
                self.add_module(ctx, path_ctx, m, name, doc_aliases);
            }
            _ => (),
        });
    }

    pub(crate) fn add_path_resolution(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        local_name: hir::Name,
        resolution: hir::ScopeDef,
        doc_aliases: Vec<syntax::SmolStr>,
    ) {
        let is_private_editable = match ctx.def_is_visible(&resolution) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        self.add(
            render_path_resolution(
                RenderContext::new(ctx)
                    .private_editable(is_private_editable)
                    .doc_aliases(doc_aliases),
                path_ctx,
                local_name,
                resolution,
            )
            .build(ctx.db),
        );
    }

    pub(crate) fn add_pattern_resolution(
        &mut self,
        ctx: &CompletionContext<'_>,
        pattern_ctx: &PatternContext,
        local_name: hir::Name,
        resolution: hir::ScopeDef,
    ) {
        let is_private_editable = match ctx.def_is_visible(&resolution) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        self.add(
            render_pattern_resolution(
                RenderContext::new(ctx).private_editable(is_private_editable),
                pattern_ctx,
                local_name,
                resolution,
            )
            .build(ctx.db),
        );
    }

    pub(crate) fn add_enum_variants(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        e: hir::Enum,
    ) {
        if !ctx.check_stability_and_hidden(e) {
            return;
        }
        e.variants(ctx.db)
            .into_iter()
            .for_each(|variant| self.add_enum_variant(ctx, path_ctx, variant, None));
    }

    pub(crate) fn add_module(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        module: hir::Module,
        local_name: hir::Name,
        doc_aliases: Vec<syntax::SmolStr>,
    ) {
        self.add_path_resolution(
            ctx,
            path_ctx,
            local_name,
            hir::ScopeDef::ModuleDef(module.into()),
            doc_aliases,
        );
    }

    pub(crate) fn add_macro(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        mac: hir::Macro,
        local_name: hir::Name,
    ) {
        let is_private_editable = match ctx.is_visible(&mac) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        self.add(
            render_macro(
                RenderContext::new(ctx).private_editable(is_private_editable),
                path_ctx,
                local_name,
                mac,
            )
            .build(ctx.db),
        );
    }

    pub(crate) fn add_function(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        func: hir::Function,
        local_name: Option<hir::Name>,
    ) {
        let is_private_editable = match ctx.is_visible(&func) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        let doc_aliases = ctx.doc_aliases(&func);
        self.add(
            render_fn(
                RenderContext::new(ctx)
                    .private_editable(is_private_editable)
                    .doc_aliases(doc_aliases),
                path_ctx,
                local_name,
                func,
            )
            .build(ctx.db),
        );
    }

    pub(crate) fn add_method(
        &mut self,
        ctx: &CompletionContext<'_>,
        dot_access: &DotAccess<'_>,
        func: hir::Function,
        receiver: Option<SmolStr>,
        local_name: Option<hir::Name>,
    ) {
        let is_private_editable = match ctx.is_visible(&func) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        let doc_aliases = ctx.doc_aliases(&func);
        self.add(
            render_method(
                RenderContext::new(ctx)
                    .private_editable(is_private_editable)
                    .doc_aliases(doc_aliases),
                dot_access,
                receiver,
                local_name,
                func,
            )
            .build(ctx.db),
        );
    }

    pub(crate) fn add_method_with_import(
        &mut self,
        ctx: &CompletionContext<'_>,
        dot_access: &DotAccess<'_>,
        func: hir::Function,
        import: LocatedImport,
    ) {
        let is_private_editable = match ctx.is_visible(&func) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        let doc_aliases = ctx.doc_aliases(&func);
        self.add(
            render_method(
                RenderContext::new(ctx)
                    .private_editable(is_private_editable)
                    .doc_aliases(doc_aliases)
                    .import_to_add(Some(import)),
                dot_access,
                None,
                None,
                func,
            )
            .build(ctx.db),
        );
    }

    pub(crate) fn add_const(&mut self, ctx: &CompletionContext<'_>, konst: hir::Const) {
        let is_private_editable = match ctx.is_visible(&konst) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        self.add_opt(render_const(
            RenderContext::new(ctx).private_editable(is_private_editable),
            konst,
        ));
    }

    pub(crate) fn add_type_alias(
        &mut self,
        ctx: &CompletionContext<'_>,
        type_alias: hir::TypeAlias,
    ) {
        let is_private_editable = match ctx.is_visible(&type_alias) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        self.add_opt(render_type_alias(
            RenderContext::new(ctx).private_editable(is_private_editable),
            type_alias,
        ));
    }

    pub(crate) fn add_type_alias_with_eq(
        &mut self,
        ctx: &CompletionContext<'_>,
        type_alias: hir::TypeAlias,
    ) {
        if !ctx.check_stability(Some(&type_alias.attrs(ctx.db))) {
            return;
        }
        self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias));
    }

    pub(crate) fn add_qualified_enum_variant(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        variant: hir::Variant,
        path: hir::ModPath,
    ) {
        if !ctx.check_stability_and_hidden(variant) {
            return;
        }
        if let Some(builder) =
            render_variant_lit(RenderContext::new(ctx), path_ctx, None, variant, Some(path))
        {
            self.add(builder.build(ctx.db));
        }
    }

    pub(crate) fn add_enum_variant(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        variant: hir::Variant,
        local_name: Option<hir::Name>,
    ) {
        if !ctx.check_stability_and_hidden(variant) {
            return;
        }
        if let PathCompletionCtx { kind: PathKind::Pat { pat_ctx }, .. } = path_ctx {
            cov_mark::hit!(enum_variant_pattern_path);
            self.add_variant_pat(ctx, pat_ctx, Some(path_ctx), variant, local_name);
            return;
        }

        if let Some(builder) =
            render_variant_lit(RenderContext::new(ctx), path_ctx, local_name, variant, None)
        {
            self.add(builder.build(ctx.db));
        }
    }

    pub(crate) fn add_field(
        &mut self,
        ctx: &CompletionContext<'_>,
        dot_access: &DotAccess<'_>,
        receiver: Option<SmolStr>,
        field: hir::Field,
        ty: &hir::Type<'_>,
    ) {
        let is_private_editable = match ctx.is_visible(&field) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        let doc_aliases = ctx.doc_aliases(&field);
        let item = render_field(
            RenderContext::new(ctx).private_editable(is_private_editable).doc_aliases(doc_aliases),
            dot_access,
            receiver,
            field,
            ty,
        );
        self.add(item);
    }

    pub(crate) fn add_struct_literal(
        &mut self,
        ctx: &CompletionContext<'_>,
        path_ctx: &PathCompletionCtx<'_>,
        strukt: hir::Struct,
        path: Option<hir::ModPath>,
        local_name: Option<hir::Name>,
    ) {
        let is_private_editable = match ctx.is_visible(&strukt) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        if let Some(builder) = render_struct_literal(
            RenderContext::new(ctx).private_editable(is_private_editable),
            path_ctx,
            strukt,
            path,
            local_name,
        ) {
            self.add(builder.build(ctx.db));
        }
    }

    pub(crate) fn add_union_literal(
        &mut self,
        ctx: &CompletionContext<'_>,
        un: hir::Union,
        path: Option<hir::ModPath>,
        local_name: Option<hir::Name>,
    ) {
        let is_private_editable = match ctx.is_visible(&un) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        let item = render_union_literal(
            RenderContext::new(ctx).private_editable(is_private_editable),
            un,
            path,
            local_name,
        );
        self.add_opt(item);
    }

    pub(crate) fn add_tuple_field(
        &mut self,
        ctx: &CompletionContext<'_>,
        receiver: Option<SmolStr>,
        field: usize,
        ty: &hir::Type<'_>,
    ) {
        // Only used for (unnamed) tuples, whose all fields *are* stable. No need to check
        // stability here.
        let item = render_tuple_field(RenderContext::new(ctx), receiver, field, ty);
        self.add(item);
    }

    pub(crate) fn add_lifetime(&mut self, ctx: &CompletionContext<'_>, name: hir::Name) {
        CompletionItem::new(
            SymbolKind::LifetimeParam,
            ctx.source_range(),
            name.display_no_db(ctx.edition).to_smolstr(),
            ctx.edition,
        )
        .add_to(self, ctx.db)
    }

    pub(crate) fn add_label(&mut self, ctx: &CompletionContext<'_>, name: hir::Name) {
        CompletionItem::new(
            SymbolKind::Label,
            ctx.source_range(),
            name.display_no_db(ctx.edition).to_smolstr(),
            ctx.edition,
        )
        .add_to(self, ctx.db)
    }

    pub(crate) fn add_variant_pat(
        &mut self,
        ctx: &CompletionContext<'_>,
        pattern_ctx: &PatternContext,
        path_ctx: Option<&PathCompletionCtx<'_>>,
        variant: hir::Variant,
        local_name: Option<hir::Name>,
    ) {
        if !ctx.check_stability_and_hidden(variant) {
            return;
        }
        self.add_opt(render_variant_pat(
            RenderContext::new(ctx),
            pattern_ctx,
            path_ctx,
            variant,
            local_name,
            None,
        ));
    }

    pub(crate) fn add_qualified_variant_pat(
        &mut self,
        ctx: &CompletionContext<'_>,
        pattern_ctx: &PatternContext,
        variant: hir::Variant,
        path: hir::ModPath,
    ) {
        if !ctx.check_stability_and_hidden(variant) {
            return;
        }
        let path = Some(&path);
        self.add_opt(render_variant_pat(
            RenderContext::new(ctx),
            pattern_ctx,
            None,
            variant,
            None,
            path,
        ));
    }

    pub(crate) fn add_struct_pat(
        &mut self,
        ctx: &CompletionContext<'_>,
        pattern_ctx: &PatternContext,
        strukt: hir::Struct,
        local_name: Option<hir::Name>,
    ) {
        let is_private_editable = match ctx.is_visible(&strukt) {
            Visible::Yes => false,
            Visible::Editable => true,
            Visible::No => return,
        };
        self.add_opt(render_struct_pat(
            RenderContext::new(ctx).private_editable(is_private_editable),
            pattern_ctx,
            strukt,
            local_name,
        ));
    }

    pub(crate) fn suggest_name(&mut self, ctx: &CompletionContext<'_>, name: &str) {
        let item = CompletionItem::new(
            CompletionItemKind::Binding,
            ctx.source_range(),
            SmolStr::from(name),
            ctx.edition,
        );
        item.add_to(self, ctx.db);
    }
}

/// Calls the callback for each variant of the provided enum with the path to the variant.
/// Skips variants that are visible with single segment paths.
fn enum_variants_with_paths(
    acc: &mut Completions,
    ctx: &CompletionContext<'_>,
    enum_: hir::Enum,
    impl_: &Option<ast::Impl>,
    cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::Variant, hir::ModPath),
) {
    let mut process_variant = |variant: Variant| {
        let self_path = hir::ModPath::from_segments(
            hir::PathKind::Plain,
            iter::once(Name::new_symbol_root(sym::Self_)).chain(iter::once(variant.name(ctx.db))),
        );

        cb(acc, ctx, variant, self_path);
    };

    let variants = enum_.variants(ctx.db);

    if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_))
        && impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_))
    {
        variants.iter().for_each(|variant| process_variant(*variant));
    }

    for variant in variants {
        if let Some(path) = ctx.module.find_path(
            ctx.db,
            hir::ModuleDef::from(variant),
            ctx.config.import_path_config(ctx.is_nightly),
        ) {
            // Variants with trivial paths are already added by the existing completion logic,
            // so we should avoid adding these twice
            if path.segments().len() > 1 {
                cb(acc, ctx, variant, path);
            }
        }
    }
}

pub(super) fn complete_name(
    acc: &mut Completions,
    ctx: &CompletionContext<'_>,
    NameContext { name, kind }: &NameContext,
) {
    match kind {
        NameKind::Const => {
            item_list::trait_impl::complete_trait_impl_const(acc, ctx, name);
        }
        NameKind::Function => {
            item_list::trait_impl::complete_trait_impl_fn(acc, ctx, name);
        }
        NameKind::IdentPat(pattern_ctx) => {
            if ctx.token.kind() != syntax::T![_] {
                complete_patterns(acc, ctx, pattern_ctx)
            }
        }
        NameKind::Module(mod_under_caret) => {
            mod_::complete_mod(acc, ctx, mod_under_caret);
        }
        NameKind::TypeAlias => {
            item_list::trait_impl::complete_trait_impl_type_alias(acc, ctx, name);
        }
        NameKind::RecordField => {
            field::complete_field_list_record_variant(acc, ctx);
        }
        NameKind::ConstParam
        | NameKind::Enum
        | NameKind::MacroDef
        | NameKind::MacroRules
        | NameKind::Rename
        | NameKind::SelfParam
        | NameKind::Static
        | NameKind::Struct
        | NameKind::Trait
        | NameKind::TypeParam
        | NameKind::Union
        | NameKind::Variant => (),
    }
}

pub(super) fn complete_name_ref(
    acc: &mut Completions,
    ctx: &CompletionContext<'_>,
    NameRefContext { nameref, kind }: &NameRefContext<'_>,
) {
    match kind {
        NameRefKind::Path(path_ctx) => {
            flyimport::import_on_the_fly_path(acc, ctx, path_ctx);

            match &path_ctx.kind {
                PathKind::Expr { expr_ctx } => {
                    expr::complete_expr_path(acc, ctx, path_ctx, expr_ctx);
                    expr::complete_expr(acc, ctx);

                    dot::complete_undotted_self(acc, ctx, path_ctx, expr_ctx);
                    item_list::complete_item_list_in_expr(acc, ctx, path_ctx, expr_ctx);
                    snippet::complete_expr_snippet(acc, ctx, path_ctx, expr_ctx);
                }
                PathKind::Type { location } => {
                    r#type::complete_type_path(acc, ctx, path_ctx, location);

                    match location {
                        TypeLocation::TupleField => {
                            field::complete_field_list_tuple_variant(acc, ctx, path_ctx);
                        }
                        TypeLocation::TypeAscription(ascription) => {
                            r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
                        }
                        TypeLocation::GenericArg { .. }
                        | TypeLocation::AssocConstEq
                        | TypeLocation::AssocTypeEq
                        | TypeLocation::TypeBound
                        | TypeLocation::ImplTarget
                        | TypeLocation::ImplTrait
                        | TypeLocation::Other => (),
                    }
                }
                PathKind::Attr { attr_ctx } => {
                    attribute::complete_attribute_path(acc, ctx, path_ctx, attr_ctx);
                }
                PathKind::Derive { existing_derives } => {
                    attribute::complete_derive_path(acc, ctx, path_ctx, existing_derives);
                }
                PathKind::Item { kind } => {
                    item_list::complete_item_list(acc, ctx, path_ctx, kind);

                    snippet::complete_item_snippet(acc, ctx, path_ctx, kind);
                    if let ItemListKind::TraitImpl(impl_) = kind {
                        item_list::trait_impl::complete_trait_impl_item_by_name(
                            acc, ctx, path_ctx, nameref, impl_,
                        );
                    }
                }
                PathKind::Pat { .. } => {
                    pattern::complete_pattern_path(acc, ctx, path_ctx);
                }
                PathKind::Vis { has_in_token } => {
                    vis::complete_vis_path(acc, ctx, path_ctx, has_in_token);
                }
                PathKind::Use => {
                    use_::complete_use_path(acc, ctx, path_ctx, nameref);
                }
            }
        }
        NameRefKind::ExternCrate => extern_crate::complete_extern_crate(acc, ctx),
        NameRefKind::DotAccess(dot_access) => {
            flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
            dot::complete_dot(acc, ctx, dot_access);
            postfix::complete_postfix(acc, ctx, dot_access);
        }
        NameRefKind::Keyword(item) => {
            keyword::complete_for_and_where(acc, ctx, item);
        }
        NameRefKind::RecordExpr { dot_prefix, expr } => {
            record::complete_record_expr_fields(acc, ctx, expr, dot_prefix);
        }
        NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
    }
}

fn complete_patterns(
    acc: &mut Completions,
    ctx: &CompletionContext<'_>,
    pattern_ctx: &PatternContext,
) {
    flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
    fn_param::complete_fn_param(acc, ctx, pattern_ctx);
    pattern::complete_pattern(acc, ctx, pattern_ctx);
    record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
}
