//! 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 {
            if 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_)) {
        if 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);
}
