use rustc_ast::{self as ast, AsmMacro};
use rustc_span::{Span, Symbol, kw};

use super::{ExpKeywordPair, ForceCollect, IdentIsRaw, Trailing, UsePreAttrPos};
use crate::{PResult, Parser, diagnostics, exp, token};

/// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise
/// not validated at all.
pub struct AsmArg {
    pub kind: AsmArgKind,
    pub attributes: AsmAttrVec,
    pub span: Span,
}

pub enum AsmArgKind {
    Template(Box<ast::Expr>),
    Operand(Option<Symbol>, ast::InlineAsmOperand),
    Options(Vec<AsmOption>),
    ClobberAbi(Vec<(Symbol, Span)>),
}

pub struct AsmOption {
    pub symbol: Symbol,
    pub span: Span,
    // A bitset, with only the bit for this option's symbol set.
    pub options: ast::InlineAsmOptions,
    // Used when suggesting to remove an option.
    pub span_with_comma: Span,
}

/// A parsed list of attributes that is not attached to any item.
/// Used to check whether `asm!` arguments are configured out.
pub struct AsmAttrVec(pub ast::AttrVec);

impl AsmAttrVec {
    fn parse<'a>(p: &mut Parser<'a>) -> PResult<'a, Self> {
        let attrs = p.parse_outer_attributes()?;

        p.collect_tokens(None, attrs, ForceCollect::No, |_, attrs| {
            Ok((Self(attrs), Trailing::No, UsePreAttrPos::No))
        })
    }
}
impl ast::HasAttrs for AsmAttrVec {
    // Follows `ast::Expr`.
    const SUPPORTS_CUSTOM_INNER_ATTRS: bool = false;

    fn attrs(&self) -> &[rustc_ast::Attribute] {
        &self.0
    }

    fn visit_attrs(&mut self, f: impl FnOnce(&mut rustc_ast::AttrVec)) {
        f(&mut self.0)
    }
}

impl ast::HasTokens for AsmAttrVec {
    fn tokens(&self) -> Option<&rustc_ast::tokenstream::LazyAttrTokenStream> {
        None
    }

    fn tokens_mut(&mut self) -> Option<&mut Option<rustc_ast::tokenstream::LazyAttrTokenStream>> {
        None
    }
}

/// Used for better error messages when operand types are used that are not
/// supported by the current macro (e.g. `in` or `out` for `global_asm!`)
///
/// returns
///
/// - `Ok(true)` if the current token matches the keyword, and was expected
/// - `Ok(false)` if the current token does not match the keyword
/// - `Err(_)` if the current token matches the keyword, but was not expected
fn eat_operand_keyword<'a>(
    p: &mut Parser<'a>,
    exp: ExpKeywordPair,
    asm_macro: AsmMacro,
) -> PResult<'a, bool> {
    if asm_macro == AsmMacro::Asm {
        Ok(p.eat_keyword(exp))
    } else {
        let span = p.token.span;
        if p.eat_keyword_noexpect(exp.kw) {
            // in gets printed as `r#in` otherwise
            let symbol = if exp.kw == kw::In { "in" } else { exp.kw.as_str() };
            Err(p.dcx().create_err(diagnostics::AsmUnsupportedOperand {
                span,
                symbol,
                macro_name: asm_macro.macro_name(),
            }))
        } else {
            Ok(false)
        }
    }
}

fn parse_asm_operand<'a>(
    p: &mut Parser<'a>,
    asm_macro: AsmMacro,
) -> PResult<'a, Option<ast::InlineAsmOperand>> {
    let dcx = p.dcx();

    Ok(Some(if eat_operand_keyword(p, exp!(In), asm_macro)? {
        let reg = parse_reg(p)?;
        if p.eat_keyword(exp!(Underscore)) {
            let err = dcx.create_err(diagnostics::AsmUnderscoreInput { span: p.token.span });
            return Err(err);
        }
        let expr = p.parse_expr()?;
        ast::InlineAsmOperand::In { reg, expr }
    } else if eat_operand_keyword(p, exp!(Out), asm_macro)? {
        let reg = parse_reg(p)?;
        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
        ast::InlineAsmOperand::Out { reg, expr, late: false }
    } else if eat_operand_keyword(p, exp!(Lateout), asm_macro)? {
        let reg = parse_reg(p)?;
        let expr = if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
        ast::InlineAsmOperand::Out { reg, expr, late: true }
    } else if eat_operand_keyword(p, exp!(Inout), asm_macro)? {
        let reg = parse_reg(p)?;
        if p.eat_keyword(exp!(Underscore)) {
            let err = dcx.create_err(diagnostics::AsmUnderscoreInput { span: p.token.span });
            return Err(err);
        }
        let expr = p.parse_expr()?;
        if p.eat(exp!(FatArrow)) {
            let out_expr =
                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: false }
        } else {
            ast::InlineAsmOperand::InOut { reg, expr, late: false }
        }
    } else if eat_operand_keyword(p, exp!(Inlateout), asm_macro)? {
        let reg = parse_reg(p)?;
        if p.eat_keyword(exp!(Underscore)) {
            let err = dcx.create_err(diagnostics::AsmUnderscoreInput { span: p.token.span });
            return Err(err);
        }
        let expr = p.parse_expr()?;
        if p.eat(exp!(FatArrow)) {
            let out_expr =
                if p.eat_keyword(exp!(Underscore)) { None } else { Some(p.parse_expr()?) };
            ast::InlineAsmOperand::SplitInOut { reg, in_expr: expr, out_expr, late: true }
        } else {
            ast::InlineAsmOperand::InOut { reg, expr, late: true }
        }
    } else if eat_operand_keyword(p, exp!(Label), asm_macro)? {
        let block = p.parse_block()?;
        ast::InlineAsmOperand::Label { block }
    } else if p.eat_keyword(exp!(Const)) {
        let anon_const = p.parse_expr_anon_const()?;
        ast::InlineAsmOperand::Const { anon_const }
    } else if p.eat_keyword(exp!(Sym)) {
        let expr = p.parse_expr()?;
        let ast::ExprKind::Path(qself, path) = &expr.kind else {
            let err = dcx.create_err(diagnostics::AsmSymNoPath { span: expr.span });
            return Err(err);
        };
        let sym =
            ast::InlineAsmSym { id: ast::DUMMY_NODE_ID, qself: qself.clone(), path: path.clone() };
        ast::InlineAsmOperand::Sym { sym }
    } else {
        return Ok(None);
    }))
}

// Public for rustfmt.
pub fn parse_asm_args<'a>(
    p: &mut Parser<'a>,
    sp: Span,
    asm_macro: AsmMacro,
) -> PResult<'a, Vec<AsmArg>> {
    let dcx = p.dcx();

    if p.token == token::Eof {
        return Err(dcx.create_err(diagnostics::AsmRequiresTemplate { span: sp }));
    }

    let mut args = Vec::new();

    let attributes = AsmAttrVec::parse(p)?;
    let first_template = p.parse_expr()?;
    args.push(AsmArg {
        span: first_template.span,
        kind: AsmArgKind::Template(first_template),
        attributes,
    });

    let mut allow_templates = true;

    while p.token != token::Eof {
        if !p.eat(exp!(Comma)) {
            if allow_templates {
                // After a template string, we always expect *only* a comma...
                return Err(dcx.create_err(diagnostics::AsmExpectedComma { span: p.token.span }));
            } else {
                // ...after that delegate to `expect` to also include the other expected tokens.
                return Err(p.expect(exp!(Comma)).err().unwrap());
            }
        }

        // Accept trailing commas.
        if p.token == token::Eof {
            break;
        }

        let attributes = AsmAttrVec::parse(p)?;
        let span_start = p.token.span;

        // Parse `clobber_abi`.
        if p.eat_keyword(exp!(ClobberAbi)) {
            allow_templates = false;

            args.push(AsmArg {
                kind: AsmArgKind::ClobberAbi(parse_clobber_abi(p)?),
                span: span_start.to(p.prev_token.span),
                attributes,
            });

            continue;
        }

        // Parse `options`.
        if p.eat_keyword(exp!(Options)) {
            allow_templates = false;

            args.push(AsmArg {
                kind: AsmArgKind::Options(parse_options(p, asm_macro)?),
                span: span_start.to(p.prev_token.span),
                attributes,
            });

            continue;
        }

        // Parse operand names.
        let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) {
            let (ident, _) = p.token.ident().unwrap();
            p.bump();
            p.expect(exp!(Eq))?;
            allow_templates = false;
            Some(ident.name)
        } else {
            None
        };

        if let Some(op) = parse_asm_operand(p, asm_macro)? {
            allow_templates = false;

            args.push(AsmArg {
                span: span_start.to(p.prev_token.span),
                kind: AsmArgKind::Operand(name, op),
                attributes,
            });
        } else if allow_templates {
            let template = p.parse_expr()?;
            // If it can't possibly expand to a string, provide diagnostics here to include other
            // things it could have been.
            match template.kind {
                ast::ExprKind::Lit(token_lit)
                    if matches!(
                        token_lit.kind,
                        token::LitKind::Str | token::LitKind::StrRaw(_)
                    ) => {}
                ast::ExprKind::MacCall(..) => {}
                _ => {
                    let err = dcx.create_err(diagnostics::AsmExpectedOther {
                        span: template.span,
                        is_inline_asm: matches!(asm_macro, AsmMacro::Asm),
                    });
                    return Err(err);
                }
            }

            args.push(AsmArg {
                span: template.span,
                kind: AsmArgKind::Template(template),
                attributes,
            });
        } else {
            p.unexpected_any()?
        }
    }

    Ok(args)
}

fn parse_options<'a>(p: &mut Parser<'a>, asm_macro: AsmMacro) -> PResult<'a, Vec<AsmOption>> {
    p.expect(exp!(OpenParen))?;

    let mut asm_options = Vec::new();

    while !p.eat(exp!(CloseParen)) {
        const OPTIONS: [(ExpKeywordPair, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
            (exp!(Pure), ast::InlineAsmOptions::PURE),
            (exp!(Nomem), ast::InlineAsmOptions::NOMEM),
            (exp!(Readonly), ast::InlineAsmOptions::READONLY),
            (exp!(PreservesFlags), ast::InlineAsmOptions::PRESERVES_FLAGS),
            (exp!(Noreturn), ast::InlineAsmOptions::NORETURN),
            (exp!(Nostack), ast::InlineAsmOptions::NOSTACK),
            (exp!(MayUnwind), ast::InlineAsmOptions::MAY_UNWIND),
            (exp!(AttSyntax), ast::InlineAsmOptions::ATT_SYNTAX),
            (exp!(Raw), ast::InlineAsmOptions::RAW),
        ];

        'blk: {
            for (exp, options) in OPTIONS {
                // Gives a more accurate list of expected next tokens.
                let kw_matched = if asm_macro.is_supported_option(options) {
                    p.eat_keyword(exp)
                } else {
                    p.eat_keyword_noexpect(exp.kw)
                };

                if kw_matched {
                    let span = p.prev_token.span;
                    let span_with_comma =
                        if p.token == token::Comma { span.to(p.token.span) } else { span };

                    asm_options.push(AsmOption { symbol: exp.kw, span, options, span_with_comma });
                    break 'blk;
                }
            }

            return p.unexpected_any();
        }

        // Allow trailing commas.
        if p.eat(exp!(CloseParen)) {
            break;
        }
        p.expect(exp!(Comma))?;
    }

    Ok(asm_options)
}

fn parse_clobber_abi<'a>(p: &mut Parser<'a>) -> PResult<'a, Vec<(Symbol, Span)>> {
    p.expect(exp!(OpenParen))?;

    if p.eat(exp!(CloseParen)) {
        return Err(p.dcx().create_err(diagnostics::NonABI { span: p.token.span }));
    }

    let mut new_abis = Vec::new();
    while !p.eat(exp!(CloseParen)) {
        match p.parse_str_lit() {
            Ok(str_lit) => {
                new_abis.push((str_lit.symbol_unescaped, str_lit.span));
            }
            Err(opt_lit) => {
                let span = opt_lit.map_or(p.token.span, |lit| lit.span);
                return Err(p.dcx().create_err(diagnostics::AsmExpectedStringLiteral { span }));
            }
        };

        // Allow trailing commas
        if p.eat(exp!(CloseParen)) {
            break;
        }
        p.expect(exp!(Comma))?;
    }

    Ok(new_abis)
}

fn parse_reg<'a>(p: &mut Parser<'a>) -> PResult<'a, ast::InlineAsmRegOrRegClass> {
    p.expect(exp!(OpenParen))?;
    let result = match p.token.uninterpolate().kind {
        token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name),
        token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => {
            ast::InlineAsmRegOrRegClass::Reg(symbol)
        }
        _ => {
            return Err(p.dcx().create_err(diagnostics::ExpectedRegisterClassOrExplicitRegister {
                span: p.token.span,
            }));
        }
    };
    p.bump();
    p.expect(exp!(CloseParen))?;
    Ok(result)
}
