//! Eager expansion related utils
//!
//! Here is a dump of a discussion from Vadim Petrochenkov about Eager Expansion and
//! Its name resolution :
//!
//! > Eagerly expanded macros (and also macros eagerly expanded by eagerly expanded macros,
//! > which actually happens in practice too!) are resolved at the location of the "root" macro
//! > that performs the eager expansion on its arguments.
//! > If some name cannot be resolved at the eager expansion time it's considered unresolved,
//! > even if becomes available later (e.g. from a glob import or other macro).
//!
//! > Eagerly expanded macros don't add anything to the module structure of the crate and
//! > don't build any speculative module structures, i.e. they are expanded in a "flat"
//! > way even if tokens in them look like modules.
//!
//! > In other words, it kinda works for simple cases for which it was originally intended,
//! > and we need to live with it because it's available on stable and widely relied upon.
//!
//!
//! See the full discussion : <https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Eager.20expansion.20of.20built-in.20macros>
use base_db::Crate;
use span::SyntaxContext;
use syntax::{AstPtr, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent, ted};
use syntax_bridge::DocCommentDesugarMode;
use triomphe::Arc;

use crate::{
    AstId, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile,
    MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
    ast::{self, AstNode},
    db::ExpandDatabase,
    mod_path::ModPath,
};

pub type EagerCallBackFn<'a> = &'a mut dyn FnMut(
    InFile<(syntax::AstPtr<ast::MacroCall>, span::FileAstId<ast::MacroCall>)>,
    MacroCallId,
);

pub fn expand_eager_macro_input(
    db: &dyn ExpandDatabase,
    krate: Crate,
    macro_call: &ast::MacroCall,
    ast_id: AstId<ast::MacroCall>,
    def: MacroDefId,
    call_site: SyntaxContext,
    resolver: &dyn Fn(&ModPath) -> Option<MacroDefId>,
    eager_callback: EagerCallBackFn<'_>,
) -> ExpandResult<Option<MacroCallId>> {
    let expand_to = ExpandTo::from_call_site(macro_call);

    // Note:
    // When `lazy_expand` is called, its *parent* file must already exist.
    // Here we store an eager macro id for the argument expanded subtree
    // for that purpose.
    let loc = MacroCallLoc {
        def,
        krate,
        kind: MacroCallKind::FnLike { ast_id, expand_to: ExpandTo::Expr, eager: None },
        ctxt: call_site,
    };
    let arg_id = db.intern_macro_call(loc);
    #[allow(deprecated)] // builtin eager macros are never derives
    let (_, _, span) = db.macro_arg(arg_id);
    let ExpandResult { value: (arg_exp, arg_exp_map), err: parse_err } =
        db.parse_macro_expansion(arg_id);

    let mut arg_map = ExpansionSpanMap::empty();

    let ExpandResult { value: expanded_eager_input, err } = {
        eager_macro_recur(
            db,
            &arg_exp_map,
            &mut arg_map,
            TextSize::new(0),
            InFile::new(arg_id.into(), arg_exp.syntax_node()),
            krate,
            call_site,
            resolver,
            eager_callback,
        )
    };
    let err = parse_err.or(err);
    if cfg!(debug_assertions) {
        arg_map.finish();
    }

    let Some((expanded_eager_input, _mapping)) = expanded_eager_input else {
        return ExpandResult { value: None, err };
    };

    let mut subtree = syntax_bridge::syntax_node_to_token_tree(
        &expanded_eager_input,
        arg_map,
        span,
        DocCommentDesugarMode::Mbe,
    );

    subtree.top_subtree_delimiter_mut().kind = crate::tt::DelimiterKind::Invisible;

    let loc = MacroCallLoc {
        def,
        krate,
        kind: MacroCallKind::FnLike {
            ast_id,
            expand_to,
            eager: Some(Arc::new(EagerCallInfo {
                arg: Arc::new(subtree),
                arg_id,
                error: err.clone(),
                span,
            })),
        },
        ctxt: call_site,
    };

    ExpandResult { value: Some(db.intern_macro_call(loc)), err }
}

fn lazy_expand(
    db: &dyn ExpandDatabase,
    def: &MacroDefId,
    macro_call: &ast::MacroCall,
    ast_id: AstId<ast::MacroCall>,
    krate: Crate,
    call_site: SyntaxContext,
    eager_callback: EagerCallBackFn<'_>,
) -> ExpandResult<(InFile<Parse<SyntaxNode>>, Arc<ExpansionSpanMap>)> {
    let expand_to = ExpandTo::from_call_site(macro_call);
    let id = def.make_call(
        db,
        krate,
        MacroCallKind::FnLike { ast_id, expand_to, eager: None },
        call_site,
    );
    eager_callback(ast_id.map(|ast_id| (AstPtr::new(macro_call), ast_id)), id);

    db.parse_macro_expansion(id).map(|parse| (InFile::new(id.into(), parse.0), parse.1))
}

fn eager_macro_recur(
    db: &dyn ExpandDatabase,
    span_map: &ExpansionSpanMap,
    expanded_map: &mut ExpansionSpanMap,
    mut offset: TextSize,
    curr: InFile<SyntaxNode>,
    krate: Crate,
    call_site: SyntaxContext,
    macro_resolver: &dyn Fn(&ModPath) -> Option<MacroDefId>,
    eager_callback: EagerCallBackFn<'_>,
) -> ExpandResult<Option<(SyntaxNode, TextSize)>> {
    let original = curr.value.clone_for_update();

    let mut replacements = Vec::new();

    // FIXME: We only report a single error inside of eager expansions
    let mut error = None;
    let mut children = original.preorder_with_tokens();

    // Collect replacement
    while let Some(child) = children.next() {
        let call = match child {
            WalkEvent::Enter(SyntaxElement::Node(child)) => match ast::MacroCall::cast(child) {
                Some(it) => {
                    children.skip_subtree();
                    it
                }
                _ => continue,
            },
            WalkEvent::Enter(_) => continue,
            WalkEvent::Leave(child) => {
                if let SyntaxElement::Token(t) = child {
                    let start = t.text_range().start();
                    offset += t.text_range().len();
                    expanded_map.push(offset, span_map.span_at(start));
                }
                continue;
            }
        };

        let def = match call.path().and_then(|path| {
            ModPath::from_src(db, path, &mut |range| span_map.span_at(range.start()).ctx)
        }) {
            Some(path) => match macro_resolver(&path) {
                Some(def) => def,
                None => {
                    let edition = krate.data(db).edition;
                    error = Some(ExpandError::other(
                        span_map.span_at(call.syntax().text_range().start()),
                        format!("unresolved macro {}", path.display(db, edition)),
                    ));
                    offset += call.syntax().text_range().len();
                    continue;
                }
            },
            None => {
                error = Some(ExpandError::other(
                    span_map.span_at(call.syntax().text_range().start()),
                    "malformed macro invocation",
                ));
                offset += call.syntax().text_range().len();
                continue;
            }
        };
        let ast_id = db.ast_id_map(curr.file_id).ast_id(&call);
        let ExpandResult { value, err } = match def.kind {
            MacroDefKind::BuiltInEager(..) => {
                let ExpandResult { value, err } = expand_eager_macro_input(
                    db,
                    krate,
                    &call,
                    curr.with_value(ast_id),
                    def,
                    call_site,
                    macro_resolver,
                    eager_callback,
                );
                match value {
                    Some(call_id) => {
                        eager_callback(
                            curr.with_value(ast_id).map(|ast_id| (AstPtr::new(&call), ast_id)),
                            call_id,
                        );
                        let ExpandResult { value: (parse, map), err: err2 } =
                            db.parse_macro_expansion(call_id);

                        map.iter().for_each(|(o, span)| expanded_map.push(o + offset, span));

                        let syntax_node = parse.syntax_node();
                        ExpandResult {
                            value: Some((
                                syntax_node.clone_for_update(),
                                offset + syntax_node.text_range().len(),
                            )),
                            err: err.or(err2),
                        }
                    }
                    None => ExpandResult { value: None, err },
                }
            }
            MacroDefKind::Declarative(..)
            | MacroDefKind::BuiltIn(..)
            | MacroDefKind::BuiltInAttr(..)
            | MacroDefKind::BuiltInDerive(..)
            | MacroDefKind::ProcMacro(..) => {
                let ExpandResult { value: (parse, tm), err } = lazy_expand(
                    db,
                    &def,
                    &call,
                    curr.with_value(ast_id),
                    krate,
                    call_site,
                    eager_callback,
                );

                // replace macro inside
                let ExpandResult { value, err: error } = eager_macro_recur(
                    db,
                    &tm,
                    expanded_map,
                    offset,
                    // FIXME: We discard parse errors here
                    parse.as_ref().map(|it| it.syntax_node()),
                    krate,
                    call_site,
                    macro_resolver,
                    eager_callback,
                );
                let err = err.or(error);

                ExpandResult { value, err }
            }
        };
        if err.is_some() {
            error = err;
        }
        // check if the whole original syntax is replaced
        if call.syntax() == &original {
            return ExpandResult { value, err: error };
        }

        match value {
            Some((insert, new_offset)) => {
                replacements.push((call, insert));
                offset = new_offset;
            }
            None => offset += call.syntax().text_range().len(),
        }
    }

    replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new));
    ExpandResult { value: Some((original, offset)), err: error }
}
