use std::borrow::Cow;

use rustc_ast as ast;
use rustc_ast::{AttrStyle, NodeId};
use rustc_errors::DiagCtxtHandle;
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::AttributeLint;
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
use rustc_session::Session;
use rustc_span::{DUMMY_SP, Span, Symbol, sym};

use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage};
use crate::parser::{ArgParser, MetaItemParser, PathParser};
use crate::session_diagnostics::ParsedDescription;
use crate::{Early, Late, OmitDoc, ShouldEmit};

/// Context created once, for example as part of the ast lowering
/// context, through which all attributes can be lowered.
pub struct AttributeParser<'sess, S: Stage = Late> {
    pub(crate) tools: Vec<Symbol>,
    pub(crate) features: Option<&'sess Features>,
    pub(crate) sess: &'sess Session,
    pub(crate) stage: S,

    /// *Only* parse attributes with this symbol.
    ///
    /// Used in cases where we want the lowering infrastructure for parse just a single attribute.
    parse_only: Option<Symbol>,
}

impl<'sess> AttributeParser<'sess, Early> {
    /// This method allows you to parse attributes *before* you have access to features or tools.
    /// One example where this is necessary, is to parse `feature` attributes themselves for
    /// example.
    ///
    /// Try to use this as little as possible. Attributes *should* be lowered during
    /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
    /// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
    ///
    /// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
    /// that symbol are picked out of the list of instructions and parsed. Those are returned.
    ///
    /// No diagnostics will be emitted when parsing limited. Lints are not emitted at all, while
    /// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed
    /// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors
    pub fn parse_limited(
        sess: &'sess Session,
        attrs: &[ast::Attribute],
        sym: Symbol,
        target_span: Span,
        target_node_id: NodeId,
        features: Option<&'sess Features>,
    ) -> Option<Attribute> {
        Self::parse_limited_should_emit(
            sess,
            attrs,
            sym,
            target_span,
            target_node_id,
            features,
            ShouldEmit::Nothing,
        )
    }

    /// This does the same as `parse_limited`, except it has a `should_emit` parameter which allows it to emit errors.
    /// Usually you want `parse_limited`, which emits no errors.
    pub fn parse_limited_should_emit(
        sess: &'sess Session,
        attrs: &[ast::Attribute],
        sym: Symbol,
        target_span: Span,
        target_node_id: NodeId,
        features: Option<&'sess Features>,
        should_emit: ShouldEmit,
    ) -> Option<Attribute> {
        let mut parsed = Self::parse_limited_all(
            sess,
            attrs,
            Some(sym),
            Target::Crate, // Does not matter, we're not going to emit errors anyways
            target_span,
            target_node_id,
            features,
            should_emit,
        );
        assert!(parsed.len() <= 1);
        parsed.pop()
    }

    /// This method allows you to parse a list of attributes *before* `rustc_ast_lowering`.
    /// This can be used for attributes that would be removed before `rustc_ast_lowering`, such as attributes on macro calls.
    ///
    /// Try to use this as little as possible. Attributes *should* be lowered during
    /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
    /// crash if you tried to do so through [`parse_limited_all`](Self::parse_limited_all).
    /// Therefore, if `parse_only` is None, then features *must* be provided.
    pub fn parse_limited_all(
        sess: &'sess Session,
        attrs: &[ast::Attribute],
        parse_only: Option<Symbol>,
        target: Target,
        target_span: Span,
        target_node_id: NodeId,
        features: Option<&'sess Features>,
        emit_errors: ShouldEmit,
    ) -> Vec<Attribute> {
        let mut p =
            Self { features, tools: Vec::new(), parse_only, sess, stage: Early { emit_errors } };
        p.parse_attribute_list(
            attrs,
            target_span,
            target_node_id,
            target,
            OmitDoc::Skip,
            std::convert::identity,
            |lint| {
                crate::lints::emit_attribute_lint(&lint, sess);
            },
        )
    }

    /// This method parses a single attribute, using `parse_fn`.
    /// This is useful if you already know what exact attribute this is, and want to parse it.
    pub fn parse_single<T>(
        sess: &'sess Session,
        attr: &ast::Attribute,
        target_span: Span,
        target_node_id: NodeId,
        features: Option<&'sess Features>,
        emit_errors: ShouldEmit,
        parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>,
        template: &AttributeTemplate,
    ) -> Option<T> {
        let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
            panic!("parse_single called on a doc attr")
        };
        let parts =
            normal_attr.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();
        let meta_parser = MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors)?;
        let path = meta_parser.path();
        let args = meta_parser.args();
        Self::parse_single_args(
            sess,
            attr.span,
            normal_attr.item.span(),
            attr.style,
            path.get_attribute_path(),
            ParsedDescription::Attribute,
            target_span,
            target_node_id,
            features,
            emit_errors,
            args,
            parse_fn,
            template,
        )
    }

    /// This method is equivalent to `parse_single`, but parses arguments using `parse_fn` using manually created `args`.
    /// This is useful when you want to parse other things than attributes using attribute parsers.
    pub fn parse_single_args<T, I>(
        sess: &'sess Session,
        attr_span: Span,
        inner_span: Span,
        attr_style: AttrStyle,
        attr_path: AttrPath,
        parsed_description: ParsedDescription,
        target_span: Span,
        target_node_id: NodeId,
        features: Option<&'sess Features>,
        emit_errors: ShouldEmit,
        args: &I,
        parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> T,
        template: &AttributeTemplate,
    ) -> T {
        let mut parser = Self {
            features,
            tools: Vec::new(),
            parse_only: None,
            sess,
            stage: Early { emit_errors },
        };
        let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
            shared: SharedContext {
                cx: &mut parser,
                target_span,
                target_id: target_node_id,
                emit_lint: &mut |lint| {
                    crate::lints::emit_attribute_lint(&lint, sess);
                },
            },
            attr_span,
            inner_span,
            attr_style,
            parsed_description,
            template,
            attr_path,
        };
        parse_fn(&mut cx, args)
    }
}

impl<'sess, S: Stage> AttributeParser<'sess, S> {
    pub fn new(
        sess: &'sess Session,
        features: &'sess Features,
        tools: Vec<Symbol>,
        stage: S,
    ) -> Self {
        Self { features: Some(features), tools, parse_only: None, sess, stage }
    }

    pub(crate) fn sess(&self) -> &'sess Session {
        &self.sess
    }

    pub(crate) fn features(&self) -> &'sess Features {
        self.features.expect("features not available at this point in the compiler")
    }

    pub(crate) fn features_option(&self) -> Option<&'sess Features> {
        self.features
    }

    pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
        self.sess().dcx()
    }

    /// Parse a list of attributes.
    ///
    /// `target_span` is the span of the thing this list of attributes is applied to,
    /// and when `omit_doc` is set, doc attributes are filtered out.
    pub fn parse_attribute_list(
        &mut self,
        attrs: &[ast::Attribute],
        target_span: Span,
        target_id: S::Id,
        target: Target,
        omit_doc: OmitDoc,

        lower_span: impl Copy + Fn(Span) -> Span,
        mut emit_lint: impl FnMut(AttributeLint<S::Id>),
    ) -> Vec<Attribute> {
        let mut attributes = Vec::new();
        let mut attr_paths = Vec::new();

        for attr in attrs {
            // If we're only looking for a single attribute, skip all the ones we don't care about.
            if let Some(expected) = self.parse_only {
                if !attr.has_name(expected) {
                    continue;
                }
            }

            // Sometimes, for example for `#![doc = include_str!("readme.md")]`,
            // doc still contains a non-literal. You might say, when we're lowering attributes
            // that's expanded right? But no, sometimes, when parsing attributes on macros,
            // we already use the lowering logic and these are still there. So, when `omit_doc`
            // is set we *also* want to ignore these.
            if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
                continue;
            }

            match &attr.kind {
                ast::AttrKind::DocComment(comment_kind, symbol) => {
                    if omit_doc == OmitDoc::Skip {
                        continue;
                    }

                    attributes.push(Attribute::Parsed(AttributeKind::DocComment {
                        style: attr.style,
                        kind: *comment_kind,
                        span: lower_span(attr.span),
                        comment: *symbol,
                    }))
                }
                // // FIXME: make doc attributes go through a proper attribute parser
                // ast::AttrKind::Normal(n) if n.has_name(sym::doc) => {
                //     let p = GenericMetaItemParser::from_attr(&n, self.dcx());
                //
                //     attributes.push(Attribute::Parsed(AttributeKind::DocComment {
                //         style: attr.style,
                //         kind: CommentKind::Line,
                //         span: attr.span,
                //         comment: p.args().name_value(),
                //     }))
                // }
                ast::AttrKind::Normal(n) => {
                    attr_paths.push(PathParser(Cow::Borrowed(&n.item.path)));

                    let parts =
                        n.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();

                    if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) {
                        let Some(parser) = MetaItemParser::from_attr(
                            n,
                            &parts,
                            &self.sess.psess,
                            self.stage.should_emit(),
                        ) else {
                            continue;
                        };
                        let path = parser.path();
                        let args = parser.args();
                        for accept in accepts {
                            let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
                                shared: SharedContext {
                                    cx: self,
                                    target_span,
                                    target_id,
                                    emit_lint: &mut emit_lint,
                                },
                                attr_span: lower_span(attr.span),
                                inner_span: lower_span(attr.get_normal_item().span()),
                                attr_style: attr.style,
                                parsed_description: ParsedDescription::Attribute,
                                template: &accept.template,
                                attr_path: path.get_attribute_path(),
                            };

                            (accept.accept_fn)(&mut cx, args);
                            if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
                                Self::check_target(&accept.allowed_targets, target, &mut cx);
                            }
                        }
                    } else {
                        // If we're here, we must be compiling a tool attribute... Or someone
                        // forgot to parse their fancy new attribute. Let's warn them in any case.
                        // If you are that person, and you really think your attribute should
                        // remain unparsed, carefully read the documentation in this module and if
                        // you still think so you can add an exception to this assertion.

                        // FIXME(jdonszelmann): convert other attributes, and check with this that
                        // we caught em all
                        // const FIXME_TEMPORARY_ATTR_ALLOWLIST: &[Symbol] = &[sym::cfg];
                        // assert!(
                        //     self.tools.contains(&parts[0]) || true,
                        //     // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
                        //     "attribute {path} wasn't parsed and isn't a know tool attribute",
                        // );

                        attributes.push(Attribute::Unparsed(Box::new(AttrItem {
                            path: AttrPath::from_ast(&n.item.path),
                            args: self.lower_attr_args(&n.item.args, lower_span),
                            id: HashIgnoredAttrId { attr_id: attr.id },
                            style: attr.style,
                            span: lower_span(attr.span),
                        })));
                    }
                }
            }
        }

        let mut parsed_attributes = Vec::new();
        for f in &S::parsers().finalizers {
            if let Some(attr) = f(&mut FinalizeContext {
                shared: SharedContext {
                    cx: self,
                    target_span,
                    target_id,
                    emit_lint: &mut emit_lint,
                },
                all_attrs: &attr_paths,
            }) {
                parsed_attributes.push(Attribute::Parsed(attr));
            }
        }

        attributes.extend(parsed_attributes);

        attributes
    }

    /// Returns whether there is a parser for an attribute with this name
    pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
        Late::parsers().accepters.contains_key(path)
    }

    fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
        match args {
            ast::AttrArgs::Empty => AttrArgs::Empty,
            ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
            // This is an inert key-value attribute - it will never be visible to macros
            // after it gets lowered to HIR. Therefore, we can extract literals to handle
            // nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
            ast::AttrArgs::Eq { eq_span, expr } => {
                // In valid code the value always ends up as a single literal. Otherwise, a dummy
                // literal suffices because the error is handled elsewhere.
                let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
                    && let Ok(lit) =
                        ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
                {
                    lit
                } else {
                    let guar = self.dcx().span_delayed_bug(
                        args.span().unwrap_or(DUMMY_SP),
                        "expr in place where literal is expected (builtin attr parsing)",
                    );
                    ast::MetaItemLit {
                        symbol: sym::dummy,
                        suffix: None,
                        kind: ast::LitKind::Err(guar),
                        span: DUMMY_SP,
                    }
                };
                AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
            }
        }
    }
}
