use std::iter;

use rustc_ast::{self as ast, DUMMY_NODE_ID, Expr, ExprKind};
use rustc_ast_pretty::pprust;
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::{Span, Symbol, kw, sym};
use smallvec::SmallVec;

use crate::base::{Annotatable, ExtCtxt};
use crate::expand::{AstFragment, AstFragmentKind};

#[derive(Default)]
pub struct MacroStat {
    /// Number of uses of the macro.
    pub uses: usize,

    /// Number of lines of code (when pretty-printed).
    pub lines: usize,

    /// Number of bytes of code (when pretty-printed).
    pub bytes: usize,
}

pub(crate) fn elems_to_string<T>(elems: &SmallVec<[T; 1]>, f: impl Fn(&T) -> String) -> String {
    let mut s = String::new();
    for (i, elem) in elems.iter().enumerate() {
        if i > 0 {
            s.push('\n');
        }
        s.push_str(&f(elem));
    }
    s
}

pub(crate) fn unreachable_to_string<T>(_: &T) -> String {
    unreachable!()
}

pub(crate) fn update_bang_macro_stats(
    ecx: &mut ExtCtxt<'_>,
    fragment_kind: AstFragmentKind,
    span: Span,
    mac: Box<ast::MacCall>,
    fragment: &AstFragment,
) {
    // Does this path match any of the include macros, e.g. `include!`?
    // Ignore them. They would have large numbers but are entirely
    // unsurprising and uninteresting.
    let is_include_path = mac.path == sym::include
        || mac.path == sym::include_bytes
        || mac.path == sym::include_str
        || mac.path == [sym::std, sym::include].as_slice() // std::include
        || mac.path == [sym::std, sym::include_bytes].as_slice() // std::include_bytes
        || mac.path == [sym::std, sym::include_str].as_slice(); // std::include_str
    if is_include_path {
        return;
    }

    // The call itself (e.g. `println!("hi")`) is the input. Need to wrap
    // `mac` in something printable; `ast::Expr` is as good as anything
    // else.
    let expr = Expr {
        id: DUMMY_NODE_ID,
        kind: ExprKind::MacCall(mac),
        span: Default::default(),
        attrs: Default::default(),
        tokens: None,
    };
    let input = pprust::expr_to_string(&expr);

    // Get `mac` back out of `expr`.
    let ast::Expr { kind: ExprKind::MacCall(mac), .. } = expr else { unreachable!() };

    update_macro_stats(ecx, MacroKind::Bang, fragment_kind, span, &mac.path, &input, fragment);
}

pub(crate) fn update_attr_macro_stats(
    ecx: &mut ExtCtxt<'_>,
    fragment_kind: AstFragmentKind,
    span: Span,
    path: &ast::Path,
    attr: &ast::Attribute,
    item: Annotatable,
    fragment: &AstFragment,
) {
    // Does this path match `#[derive(...)]` in any of its forms? If so,
    // ignore it because the individual derives will go through the
    // `Invocation::Derive` handling separately.
    let is_derive_path = *path == sym::derive
        // ::core::prelude::v1::derive
        || *path == [kw::PathRoot, sym::core, sym::prelude, sym::v1, sym::derive].as_slice();
    if is_derive_path {
        return;
    }

    // The attribute plus the item itself constitute the input, which we
    // measure.
    let input = format!(
        "{}\n{}",
        pprust::attribute_to_string(attr),
        fragment_kind.expect_from_annotatables(iter::once(item)).to_string(),
    );
    update_macro_stats(ecx, MacroKind::Attr, fragment_kind, span, path, &input, fragment);
}

pub(crate) fn update_derive_macro_stats(
    ecx: &mut ExtCtxt<'_>,
    fragment_kind: AstFragmentKind,
    span: Span,
    path: &ast::Path,
    fragment: &AstFragment,
) {
    // Use something like `#[derive(Clone)]` for the measured input, even
    // though it may have actually appeared in a multi-derive attribute
    // like `#[derive(Clone, Copy, Debug)]`.
    let input = format!("#[derive({})]", pprust::path_to_string(path));
    update_macro_stats(ecx, MacroKind::Derive, fragment_kind, span, path, &input, fragment);
}

pub(crate) fn update_macro_stats(
    ecx: &mut ExtCtxt<'_>,
    macro_kind: MacroKind,
    fragment_kind: AstFragmentKind,
    span: Span,
    path: &ast::Path,
    input: &str,
    fragment: &AstFragment,
) {
    // Measure the size of the output by pretty-printing it and counting
    // the lines and bytes.
    let name = Symbol::intern(&pprust::path_to_string(path));
    let output = fragment.to_string();
    let num_lines = output.trim_end().split('\n').count();
    let num_bytes = output.len();

    // This code is useful for debugging `-Zmacro-stats`. For every
    // invocation it prints the full input and output.
    if false {
        let name = ExpnKind::Macro(macro_kind, name).descr();
        let crate_name = &ecx.ecfg.crate_name;
        let span = ecx
            .sess
            .source_map()
            .span_to_string(span, rustc_span::FileNameDisplayPreference::Local);
        eprint!(
            "\
            -------------------------------\n\
            {name}: [{crate_name}] ({fragment_kind:?}) {span}\n\
            -------------------------------\n\
            {input}\n\
            -- {num_lines} lines, {num_bytes} bytes --\n\
            {output}\n\
        "
        );
    }

    // The recorded size is the difference between the input and the output.
    let entry = ecx.macro_stats.entry((name, macro_kind)).or_insert(MacroStat::default());
    entry.uses += 1;
    entry.lines += num_lines;
    entry.bytes += num_bytes;
}
