use rustc_ast as ast;
use rustc_ast::token::{self, MetaVarKind};
use rustc_ast::tokenstream::ParserRange;
use rustc_ast::{AttrItemKind, Attribute, attr};
use rustc_errors::codes::*;
use rustc_errors::{Diag, PResult, inline_fluent};
use rustc_span::{BytePos, Span};
use thin_vec::ThinVec;
use tracing::debug;

use super::{
    AllowConstBlockItems, AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle,
    Trailing, UsePreAttrPos,
};
use crate::parser::FnContext;
use crate::{errors, exp};

// Public for rustfmt usage
#[derive(Debug)]
pub enum InnerAttrPolicy {
    Permitted,
    Forbidden(Option<InnerAttrForbiddenReason>),
}

#[derive(Clone, Copy, Debug)]
pub enum InnerAttrForbiddenReason {
    InCodeBlock,
    AfterOuterDocComment { prev_doc_comment_span: Span },
    AfterOuterAttribute { prev_outer_attr_sp: Span },
}

enum OuterAttributeType {
    DocComment,
    DocBlockComment,
    Attribute,
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum AllowLeadingUnsafe {
    Yes,
    No,
}

impl<'a> Parser<'a> {
    /// Parses attributes that appear before an item.
    pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
        let mut outer_attrs = ast::AttrVec::new();
        let mut just_parsed_doc_comment = false;
        let start_pos = self.num_bump_calls;
        loop {
            let attr = if self.check(exp!(Pound)) {
                let prev_outer_attr_sp = outer_attrs.last().map(|attr: &Attribute| attr.span);

                let inner_error_reason = if just_parsed_doc_comment {
                    Some(InnerAttrForbiddenReason::AfterOuterDocComment {
                        prev_doc_comment_span: prev_outer_attr_sp.unwrap(),
                    })
                } else {
                    prev_outer_attr_sp.map(|prev_outer_attr_sp| {
                        InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }
                    })
                };
                let inner_parse_policy = InnerAttrPolicy::Forbidden(inner_error_reason);
                just_parsed_doc_comment = false;
                Some(self.parse_attribute(inner_parse_policy)?)
            } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
                if attr_style != ast::AttrStyle::Outer {
                    let span = self.token.span;
                    let mut err = self
                        .dcx()
                        .struct_span_err(span, inline_fluent!("expected outer doc comment"));
                    err.code(E0753);
                    if let Some(replacement_span) = self.annotate_following_item_if_applicable(
                        &mut err,
                        span,
                        match comment_kind {
                            token::CommentKind::Line => OuterAttributeType::DocComment,
                            token::CommentKind::Block => OuterAttributeType::DocBlockComment,
                        },
                        true,
                    ) {
                        err.note(inline_fluent!(
                            "inner doc comments like this (starting with `//!` or `/*!`) can only appear before items"
                        ));
                        err.span_suggestion_verbose(
                            replacement_span,
                            inline_fluent!("you might have meant to write a regular comment"),
                            "",
                            rustc_errors::Applicability::MachineApplicable,
                        );
                    }
                    err.emit();
                }
                self.bump();
                just_parsed_doc_comment = true;
                // Always make an outer attribute - this allows us to recover from a misplaced
                // inner attribute.
                Some(attr::mk_doc_comment(
                    &self.psess.attr_id_generator,
                    comment_kind,
                    ast::AttrStyle::Outer,
                    data,
                    self.prev_token.span,
                ))
            } else {
                None
            };

            if let Some(attr) = attr {
                if attr.style == ast::AttrStyle::Outer {
                    outer_attrs.push(attr);
                }
            } else {
                break;
            }
        }
        Ok(AttrWrapper::new(outer_attrs, start_pos))
    }

    /// Matches `attribute = # ! [ meta_item ]`.
    /// `inner_parse_policy` prescribes how to handle inner attributes.
    // Public for rustfmt usage.
    pub fn parse_attribute(
        &mut self,
        inner_parse_policy: InnerAttrPolicy,
    ) -> PResult<'a, ast::Attribute> {
        debug!(
            "parse_attribute: inner_parse_policy={:?} self.token={:?}",
            inner_parse_policy, self.token
        );
        let lo = self.token.span;
        // Attributes can't have attributes of their own [Editor's note: not with that attitude]
        self.collect_tokens_no_attrs(|this| {
            let pound_hi = this.token.span.hi();
            assert!(this.eat(exp!(Pound)), "parse_attribute called in non-attribute position");

            let not_lo = this.token.span.lo();
            let style =
                if this.eat(exp!(Bang)) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };

            let mut bracket_res = this.expect(exp!(OpenBracket));
            // If `#!` is not followed by `[`
            if let Err(err) = &mut bracket_res
                && style == ast::AttrStyle::Inner
                && pound_hi == not_lo
            {
                err.note(
                    "the token sequence `#!` here looks like the start of \
                    a shebang interpreter directive but it is not",
                );
                err.help(
                    "if you meant this to be a shebang interpreter directive, \
                    move it to the very start of the file",
                );
            }
            bracket_res?;
            let item = this.parse_attr_item(ForceCollect::No)?;
            this.expect(exp!(CloseBracket))?;
            let attr_sp = lo.to(this.prev_token.span);

            // Emit error if inner attribute is encountered and forbidden.
            if style == ast::AttrStyle::Inner {
                this.error_on_forbidden_inner_attr(
                    attr_sp,
                    inner_parse_policy,
                    item.is_valid_for_outer_style(),
                );
            }

            Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp))
        })
    }

    fn annotate_following_item_if_applicable(
        &self,
        err: &mut Diag<'_>,
        span: Span,
        attr_type: OuterAttributeType,
        suggest_to_outer: bool,
    ) -> Option<Span> {
        let mut snapshot = self.create_snapshot_for_diagnostic();
        let lo = span.lo()
            + BytePos(match attr_type {
                OuterAttributeType::Attribute => 1,
                _ => 2,
            });
        let hi = lo + BytePos(1);
        let replacement_span = span.with_lo(lo).with_hi(hi);
        if let OuterAttributeType::DocBlockComment | OuterAttributeType::DocComment = attr_type {
            snapshot.bump();
        }
        loop {
            // skip any other attributes, we want the item
            if snapshot.token == token::Pound {
                if let Err(err) = snapshot.parse_attribute(InnerAttrPolicy::Permitted) {
                    err.cancel();
                    return Some(replacement_span);
                }
            } else {
                break;
            }
        }
        match snapshot.parse_item_common(
            AttrWrapper::empty(),
            true,
            false,
            FnParseMode { req_name: |_, _| true, context: FnContext::Free, req_body: true },
            ForceCollect::No,
            AllowConstBlockItems::Yes,
        ) {
            Ok(Some(item)) => {
                err.arg("item", item.kind.descr());
                err.span_label(
                    item.span,
                    match attr_type {
                        OuterAttributeType::Attribute => {
                            inline_fluent!("the inner attribute doesn't annotate this {$item}")
                        }
                        OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment => {
                            inline_fluent!("the inner doc comment doesn't annotate this {$item}")
                        }
                    },
                );
                if suggest_to_outer {
                    err.span_suggestion_verbose(
                        replacement_span,
                        match attr_type {
                            OuterAttributeType::Attribute =>  inline_fluent!("to annotate the {$item}, change the attribute from inner to outer style"),
                            OuterAttributeType::DocComment | OuterAttributeType::DocBlockComment =>  inline_fluent!("to annotate the {$item}, change the doc comment from inner to outer style"),
                        },
                        match attr_type {
                            OuterAttributeType::Attribute => "",
                            OuterAttributeType::DocBlockComment => "*",
                            OuterAttributeType::DocComment => "/",
                        },
                        rustc_errors::Applicability::MachineApplicable,
                    );
                }
                return None;
            }
            Err(item_err) => {
                item_err.cancel();
            }
            Ok(None) => {}
        }
        Some(replacement_span)
    }

    pub(super) fn error_on_forbidden_inner_attr(
        &self,
        attr_sp: Span,
        policy: InnerAttrPolicy,
        suggest_to_outer: bool,
    ) {
        if let InnerAttrPolicy::Forbidden(reason) = policy {
            let mut diag = match reason.as_ref().copied() {
                Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => {
                    self.dcx()
                        .struct_span_err(
                            attr_sp,
                            inline_fluent!(
                                "an inner attribute is not permitted following an outer doc comment"
                            ),
                        )
                        .with_span_label(
                            attr_sp,
                            inline_fluent!("not permitted following an outer doc comment"),
                        )
                        .with_span_label(
                            prev_doc_comment_span,
                            inline_fluent!("previous doc comment"),
                        )
                }
                Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self
                    .dcx()
                    .struct_span_err(
                        attr_sp,
                        inline_fluent!(
                            "an inner attribute is not permitted following an outer attribute"
                        ),
                    )
                    .with_span_label(
                        attr_sp,
                        inline_fluent!("not permitted following an outer attribute"),
                    )
                    .with_span_label(
                        prev_outer_attr_sp,
                        inline_fluent!("previous outer attribute"),
                    ),
                Some(InnerAttrForbiddenReason::InCodeBlock) | None => self.dcx().struct_span_err(
                    attr_sp,
                    inline_fluent!("an inner attribute is not permitted in this context"),
                ),
            };

            diag.note(inline_fluent!("inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files"));
            if self
                .annotate_following_item_if_applicable(
                    &mut diag,
                    attr_sp,
                    OuterAttributeType::Attribute,
                    suggest_to_outer,
                )
                .is_some()
            {
                diag.note(inline_fluent!(
                    "outer attributes, like `#[test]`, annotate the item following them"
                ));
            };
            diag.emit();
        }
    }

    /// Parses an inner part of an attribute (the path and following tokens).
    /// The tokens must be either a delimited token stream, or empty token stream,
    /// or the "legacy" key-value form.
    ///     PATH `(` TOKEN_STREAM `)`
    ///     PATH `[` TOKEN_STREAM `]`
    ///     PATH `{` TOKEN_STREAM `}`
    ///     PATH
    ///     PATH `=` UNSUFFIXED_LIT
    /// The delimiters or `=` are still put into the resulting token stream.
    pub fn parse_attr_item(&mut self, force_collect: ForceCollect) -> PResult<'a, ast::AttrItem> {
        if let Some(item) = self.eat_metavar_seq_with_matcher(
            |mv_kind| matches!(mv_kind, MetaVarKind::Meta { .. }),
            |this| this.parse_attr_item(force_collect),
        ) {
            return Ok(item);
        }

        // Attr items don't have attributes.
        self.collect_tokens(None, AttrWrapper::empty(), force_collect, |this, _empty_attrs| {
            let is_unsafe = this.eat_keyword(exp!(Unsafe));
            let unsafety = if is_unsafe {
                let unsafe_span = this.prev_token.span;
                this.expect(exp!(OpenParen))?;
                ast::Safety::Unsafe(unsafe_span)
            } else {
                ast::Safety::Default
            };

            let path = this.parse_path(PathStyle::Mod)?;
            let args = this.parse_attr_args()?;
            if is_unsafe {
                this.expect(exp!(CloseParen))?;
            }
            Ok((
                ast::AttrItem { unsafety, path, args: AttrItemKind::Unparsed(args), tokens: None },
                Trailing::No,
                UsePreAttrPos::No,
            ))
        })
    }

    /// Parses attributes that appear after the opening of an item. These should
    /// be preceded by an exclamation mark, but we accept and warn about one
    /// terminated by a semicolon.
    ///
    /// Matches `inner_attrs*`.
    pub fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
        let mut attrs = ast::AttrVec::new();
        loop {
            let start_pos = self.num_bump_calls;
            // Only try to parse if it is an inner attribute (has `!`).
            let attr = if self.check(exp!(Pound)) && self.look_ahead(1, |t| t == &token::Bang) {
                Some(self.parse_attribute(InnerAttrPolicy::Permitted)?)
            } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
                if attr_style == ast::AttrStyle::Inner {
                    self.bump();
                    Some(attr::mk_doc_comment(
                        &self.psess.attr_id_generator,
                        comment_kind,
                        attr_style,
                        data,
                        self.prev_token.span,
                    ))
                } else {
                    None
                }
            } else {
                None
            };
            if let Some(attr) = attr {
                // If we are currently capturing tokens (i.e. we are within a call to
                // `Parser::collect_tokens`) record the token positions of this inner attribute,
                // for possible later processing in a `LazyAttrTokenStream`.
                if let Capturing::Yes = self.capture_state.capturing {
                    let end_pos = self.num_bump_calls;
                    let parser_range = ParserRange(start_pos..end_pos);
                    self.capture_state.inner_attr_parser_ranges.insert(attr.id, parser_range);
                }
                attrs.push(attr);
            } else {
                break;
            }
        }
        Ok(attrs)
    }

    // Note: must be unsuffixed.
    pub(crate) fn parse_unsuffixed_meta_item_lit(&mut self) -> PResult<'a, ast::MetaItemLit> {
        let lit = self.parse_meta_item_lit()?;
        debug!("checking if {:?} is unsuffixed", lit);

        if !lit.kind.is_unsuffixed() {
            self.dcx().emit_err(errors::SuffixedLiteralInAttribute { span: lit.span });
        }

        Ok(lit)
    }

    /// Matches `COMMASEP(meta_item_inner)`.
    pub fn parse_meta_seq_top(&mut self) -> PResult<'a, ThinVec<ast::MetaItemInner>> {
        // Presumably, the majority of the time there will only be one attr.
        let mut nmis = ThinVec::with_capacity(1);
        while self.token != token::Eof {
            nmis.push(self.parse_meta_item_inner()?);
            if !self.eat(exp!(Comma)) {
                break;
            }
        }
        Ok(nmis)
    }

    /// Parse a meta item per RFC 1559.
    ///
    /// ```ebnf
    /// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ;
    /// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ;
    /// ```
    pub fn parse_meta_item(
        &mut self,
        unsafe_allowed: AllowLeadingUnsafe,
    ) -> PResult<'a, ast::MetaItem> {
        if let Some(MetaVarKind::Meta { has_meta_form }) = self.token.is_metavar_seq() {
            return if has_meta_form {
                let attr_item = self
                    .eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
                        this.parse_attr_item(ForceCollect::No)
                    })
                    .unwrap();
                Ok(attr_item.meta(attr_item.path.span).unwrap())
            } else {
                self.unexpected_any()
            };
        }

        let lo = self.token.span;
        let is_unsafe = if unsafe_allowed == AllowLeadingUnsafe::Yes {
            self.eat_keyword(exp!(Unsafe))
        } else {
            false
        };
        let unsafety = if is_unsafe {
            let unsafe_span = self.prev_token.span;
            self.expect(exp!(OpenParen))?;

            ast::Safety::Unsafe(unsafe_span)
        } else {
            ast::Safety::Default
        };

        let path = self.parse_path(PathStyle::Mod)?;
        let kind = self.parse_meta_item_kind()?;
        if is_unsafe {
            self.expect(exp!(CloseParen))?;
        }
        let span = lo.to(self.prev_token.span);

        Ok(ast::MetaItem { unsafety, path, kind, span })
    }

    pub(crate) fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> {
        Ok(if self.eat(exp!(Eq)) {
            ast::MetaItemKind::NameValue(self.parse_unsuffixed_meta_item_lit()?)
        } else if self.check(exp!(OpenParen)) {
            let (list, _) = self.parse_paren_comma_seq(|p| p.parse_meta_item_inner())?;
            ast::MetaItemKind::List(list)
        } else {
            ast::MetaItemKind::Word
        })
    }

    /// Parse an inner meta item per RFC 1559.
    ///
    /// ```ebnf
    /// MetaItemInner = UNSUFFIXED_LIT | MetaItem ;
    /// ```
    pub fn parse_meta_item_inner(&mut self) -> PResult<'a, ast::MetaItemInner> {
        match self.parse_unsuffixed_meta_item_lit() {
            Ok(lit) => return Ok(ast::MetaItemInner::Lit(lit)),
            Err(err) => err.cancel(), // we provide a better error below
        }

        match self.parse_meta_item(AllowLeadingUnsafe::No) {
            Ok(mi) => return Ok(ast::MetaItemInner::MetaItem(mi)),
            Err(err) => err.cancel(), // we provide a better error below
        }

        let mut err = errors::InvalidMetaItem {
            span: self.token.span,
            descr: super::token_descr(&self.token),
            quote_ident_sugg: None,
        };

        // Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
        // don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
        // when macro metavariables are involved.
        if self.prev_token == token::Eq
            && let token::Ident(..) = self.token.kind
        {
            let before = self.token.span.shrink_to_lo();
            while let token::Ident(..) = self.token.kind {
                self.bump();
            }
            err.quote_ident_sugg = Some(errors::InvalidMetaItemQuoteIdentSugg {
                before,
                after: self.prev_token.span.shrink_to_hi(),
            });
        }

        Err(self.dcx().create_err(err))
    }
}
