//! Functionality for obtaining data related to traits from the DB.

use crate::{RootDatabase, defs::Definition};
use hir::{AsAssocItem, Semantics, db::HirDatabase};
use rustc_hash::FxHashSet;
use syntax::{AstNode, ast};

/// Given the `impl` block, attempts to find the trait this `impl` corresponds to.
pub fn resolve_target_trait(
    sema: &Semantics<'_, RootDatabase>,
    impl_def: &ast::Impl,
) -> Option<hir::Trait> {
    let ast_path =
        impl_def.trait_().map(|it| it.syntax().clone()).and_then(ast::PathType::cast)?.path()?;

    match sema.resolve_path(&ast_path) {
        Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def),
        _ => None,
    }
}

/// Given the `impl` block, returns the list of associated items (e.g. functions or types) that are
/// missing in this `impl` block.
pub fn get_missing_assoc_items(
    sema: &Semantics<'_, RootDatabase>,
    impl_def: &ast::Impl,
) -> Vec<hir::AssocItem> {
    let imp = match sema.to_def(impl_def) {
        Some(it) => it,
        None => return vec![],
    };

    // Names must be unique between constants and functions. However, type aliases
    // may share the same name as a function or constant.
    let mut impl_fns_consts = FxHashSet::default();
    let mut impl_type = FxHashSet::default();
    let edition = imp.module(sema.db).krate().edition(sema.db);

    for item in imp.items(sema.db) {
        match item {
            hir::AssocItem::Function(it) => {
                impl_fns_consts.insert(it.name(sema.db).display(sema.db, edition).to_string());
            }
            hir::AssocItem::Const(it) => {
                if let Some(name) = it.name(sema.db) {
                    impl_fns_consts.insert(name.display(sema.db, edition).to_string());
                }
            }
            hir::AssocItem::TypeAlias(it) => {
                impl_type.insert(it.name(sema.db).display(sema.db, edition).to_string());
            }
        }
    }

    resolve_target_trait(sema, impl_def).map_or(vec![], |target_trait| {
        target_trait
            .items(sema.db)
            .into_iter()
            .filter(|i| match i {
                hir::AssocItem::Function(f) => !impl_fns_consts
                    .contains(&f.name(sema.db).display(sema.db, edition).to_string()),
                hir::AssocItem::TypeAlias(t) => {
                    !impl_type.contains(&t.name(sema.db).display(sema.db, edition).to_string())
                }
                hir::AssocItem::Const(c) => c
                    .name(sema.db)
                    .map(|n| !impl_fns_consts.contains(&n.display(sema.db, edition).to_string()))
                    .unwrap_or_default(),
            })
            .collect()
    })
}

/// Converts associated trait impl items to their trait definition counterpart
pub(crate) fn convert_to_def_in_trait(db: &dyn HirDatabase, def: Definition) -> Definition {
    (|| {
        let assoc = def.as_assoc_item(db)?;
        let trait_ = assoc.implemented_trait(db)?;
        assoc_item_of_trait(db, assoc, trait_)
    })()
    .unwrap_or(def)
}

/// If this is an trait (impl) assoc item, returns the assoc item of the corresponding trait definition.
pub(crate) fn as_trait_assoc_def(db: &dyn HirDatabase, def: Definition) -> Option<Definition> {
    let assoc = def.as_assoc_item(db)?;
    let trait_ = match assoc.container(db) {
        hir::AssocItemContainer::Trait(_) => return Some(def),
        hir::AssocItemContainer::Impl(i) => i.trait_(db),
    }?;
    assoc_item_of_trait(db, assoc, trait_)
}

fn assoc_item_of_trait(
    db: &dyn HirDatabase,
    assoc: hir::AssocItem,
    trait_: hir::Trait,
) -> Option<Definition> {
    use hir::AssocItem::*;
    let name = match assoc {
        Function(it) => it.name(db),
        Const(it) => it.name(db)?,
        TypeAlias(it) => it.name(db),
    };
    let item = trait_.items(db).into_iter().find(|it| match (it, assoc) {
        (Function(trait_func), Function(_)) => trait_func.name(db) == name,
        (Const(trait_konst), Const(_)) => trait_konst.name(db).map_or(false, |it| it == name),
        (TypeAlias(trait_type_alias), TypeAlias(_)) => trait_type_alias.name(db) == name,
        _ => false,
    })?;
    Some(Definition::from(item))
}

#[cfg(test)]
mod tests {
    use expect_test::{Expect, expect};
    use hir::FilePosition;
    use hir::Semantics;
    use salsa::AsDynDatabase;
    use span::Edition;
    use syntax::ast::{self, AstNode};
    use test_fixture::ChangeFixture;

    use crate::RootDatabase;

    /// Creates analysis from a multi-file fixture, returns positions marked with $0.
    pub(crate) fn position(
        #[rust_analyzer::rust_fixture] ra_fixture: &str,
    ) -> (RootDatabase, FilePosition) {
        let change_fixture = ChangeFixture::parse(ra_fixture);
        let mut database = RootDatabase::default();
        database.apply_change(change_fixture.change);
        let (file_id, range_or_offset) =
            change_fixture.file_position.expect("expected a marker ($0)");
        let offset = range_or_offset.expect_offset();
        (database, FilePosition { file_id, offset })
    }

    fn check_trait(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
        let (db, position) = position(ra_fixture);
        let sema = Semantics::new(&db);

        let editioned_file_id =
            crate::base_db::EditionedFileId::new(sema.db.as_dyn_database(), position.file_id);

        let file = sema.parse(editioned_file_id);
        let impl_block: ast::Impl =
            sema.find_node_at_offset_with_descend(file.syntax(), position.offset).unwrap();
        let trait_ = crate::traits::resolve_target_trait(&sema, &impl_block);
        let actual = match trait_ {
            Some(trait_) => trait_.name(&db).display(&db, Edition::CURRENT).to_string(),
            None => String::new(),
        };
        expect.assert_eq(&actual);
    }

    fn check_missing_assoc(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
        let (db, position) = position(ra_fixture);
        let sema = Semantics::new(&db);

        let editioned_file_id =
            crate::base_db::EditionedFileId::new(sema.db.as_dyn_database(), position.file_id);

        let file = sema.parse(editioned_file_id);
        let impl_block: ast::Impl =
            sema.find_node_at_offset_with_descend(file.syntax(), position.offset).unwrap();
        let items = crate::traits::get_missing_assoc_items(&sema, &impl_block);
        let actual = items
            .into_iter()
            .map(|item| item.name(&db).unwrap().display(&db, Edition::CURRENT).to_string())
            .collect::<Vec<_>>()
            .join("\n");
        expect.assert_eq(&actual);
    }

    #[test]
    fn resolve_trait() {
        check_trait(
            r#"
pub trait Foo {
    fn bar();
}
impl Foo for u8 {
    $0
}
            "#,
            expect![["Foo"]],
        );
        check_trait(
            r#"
pub trait Foo {
    fn bar();
}
impl Foo for u8 {
    fn bar() {
        fn baz() {
            $0
        }
        baz();
    }
}
            "#,
            expect![["Foo"]],
        );
        check_trait(
            r#"
pub trait Foo {
    fn bar();
}
pub struct Bar;
impl Bar {
    $0
}
            "#,
            expect![[""]],
        );
    }

    #[test]
    fn missing_assoc_items() {
        check_missing_assoc(
            r#"
pub trait Foo {
    const FOO: u8;
    fn bar();
}
impl Foo for u8 {
    $0
}"#,
            expect![[r#"
                FOO
                bar"#]],
        );

        check_missing_assoc(
            r#"
pub trait Foo {
    const FOO: u8;
    fn bar();
}
impl Foo for u8 {
    const FOO: u8 = 10;
    $0
}"#,
            expect![[r#"
                bar"#]],
        );

        check_missing_assoc(
            r#"
pub trait Foo {
    const FOO: u8;
    fn bar();
}
impl Foo for u8 {
    const FOO: u8 = 10;
    fn bar() {$0}
}"#,
            expect![[r#""#]],
        );

        check_missing_assoc(
            r#"
pub struct Foo;
impl Foo {
    fn bar() {$0}
}"#,
            expect![[r#""#]],
        );

        check_missing_assoc(
            r#"
trait Tr {
    fn required();
}
macro_rules! m {
    () => { fn required() {} };
}
impl Tr for () {
    m!();
    $0
}

            "#,
            expect![[r#""#]],
        );
    }
}
