//! moana runtime 宏
//!
//! 架构级启动汇编注入 + BSP 外设桥接函数生成。
//!
//! 标注在实现了 `BspDefine` trait 的 static 变量上，
//! 自动从关联类型推导 Console、Irqchip、Clock，无需额外参数。

use proc_macro::TokenStream;
use quote::quote;
use syn::{ItemStatic, parse::Nothing, parse_macro_input};

/// 声明 moana 运行时
///
/// 标注在实现了 `BspDefine` trait 的 static 变量上，
/// 自动生成启动汇编入口和全部 BSP 桥接函数。
///
/// # Example
/// ```text
/// #[moana_runtime]
/// static BSP: MyBoard = MyBoard::new();
/// ```
#[allow(clippy::too_many_lines)]
#[proc_macro_attribute]
pub fn moana_runtime(attr: TokenStream, input: TokenStream) -> TokenStream {
    let _ = parse_macro_input!(attr as Nothing);
    let f = parse_macro_input!(input as ItemStatic);
    let name = &f.ident;
    let ty = &f.ty;

    quote!(
        // ---- 启动汇编入口（必须在 const 块外，global_asm 是顶层 item） ----
        core::arch::global_asm!(
            ".pushsection \".head.text.entry\",\"ax\"",
            "_head:",
            #[cfg(all(target_arch = "aarch64", target_os = "none"))]
            "    b arch_primary_entry",
            #[cfg(all(target_arch = "riscv64", target_os = "none"))]
            "    j arch_primary_entry",
            ".popsection",
        );

        // ---- 原始 static 声明 ----
        #f

        const _: () = {
            use moana::bsp::BspDefine as _;
            use moana::bsp::console::ConsoleImpl as _;
            use moana::bsp::irqchip::IrqchipImpl as _;
            use moana::bsp::clocksource::ClockImpl as _;
            use core::fmt::Write as _;

            type Console = <#ty as moana::bsp::BspDefine>::Console;
            type Irqchip = <#ty as moana::bsp::BspDefine>::Irqchip;
            type Clock = <#ty as moana::bsp::BspDefine>::Clock;

            // ---- 启动回调 ----
            #[unsafe(no_mangle)]
            fn bsp_early_init() {
                #name.early_init();
            }

            #[unsafe(no_mangle)]
            fn bsp_late_init() {
                #name.late_init();
            }

            #[unsafe(no_mangle)]
            fn bsp_secondary_init() {
                #name.secondary_init();
            }

            // ---- 多核 ----
            static BSP_SMP: moana::bsp::smp::SmpDefine =
                <#ty as moana::bsp::BspDefine>::DEFINE_SMP;

            #[unsafe(no_mangle)]
            fn bsp_smp_define() -> &'static moana::bsp::smp::SmpDefine {
                &BSP_SMP
            }

            // ---- 内存 ----
            static BSP_MEMS: moana::bsp::memrange::MemDefine =
                <#ty as moana::bsp::BspDefine>::DEFINE_MEMS;

            #[unsafe(no_mangle)]
            fn bsp_mems_define() -> &'static moana::bsp::memrange::MemDefine {
                &BSP_MEMS
            }

            // ---- 控制台 ----
            static BSP_CONSOLE: moana::sync::spinlock::Spinlock<Console> =
                moana::sync::spinlock::Spinlock::new(
                    <#ty as moana::bsp::BspDefine>::DEFINE_CONSOLE,
                );

            #[unsafe(no_mangle)]
            fn bsp_console_init() {
                BSP_CONSOLE.lock_irq_save().init();
            }

            #[unsafe(no_mangle)]
            fn bsp_console_output(args: core::fmt::Arguments<'_>) {
                BSP_CONSOLE.lock_irq_save().write_fmt(args).unwrap();
            }

            // ---- 中断控制器 ----
            static BSP_IRQCHIP: Irqchip =
                <#ty as moana::bsp::BspDefine>::DEFINE_IRQCHIP;

            #[unsafe(no_mangle)]
            fn bsp_irqchip_name() -> &'static str {
                <Irqchip as moana::bsp::irqchip::IrqchipImpl>::NAME
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irqs_max() -> usize {
                <Irqchip as moana::bsp::irqchip::IrqchipImpl>::IRQS_MAX
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_ack(hwirq: u32) {
                BSP_IRQCHIP.irq_ack(hwirq);
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_eoi(hwirq: u32) {
                BSP_IRQCHIP.irq_eoi(hwirq);
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_disable(hwirq: u32) {
                BSP_IRQCHIP.irq_disable(hwirq);
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_enable(hwirq: u32) {
                BSP_IRQCHIP.irq_enable(hwirq);
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_set_affinity(
                hwirq: u32,
                cpumask: &moana::bsp::smp::Cpumask,
            ) -> moana::bsp::irqchip::Result<()> {
                BSP_IRQCHIP.irq_set_affinity(hwirq, cpumask)
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_set_type(
                hwirq: u32,
                irq_type: moana::bsp::irqchip::IrqType,
            ) -> moana::bsp::irqchip::Result<()> {
                BSP_IRQCHIP.irq_set_type(hwirq, irq_type)
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_get_irqchip_state(
                hwirq: u32,
                which: moana::bsp::irqchip::IrqchipIrqState,
            ) -> moana::bsp::irqchip::Result<bool> {
                BSP_IRQCHIP.irq_get_irqchip_state(hwirq, which)
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_set_irqchip_state(
                hwirq: u32,
                which: moana::bsp::irqchip::IrqchipIrqState,
                state: bool,
            ) -> moana::bsp::irqchip::Result<()> {
                BSP_IRQCHIP.irq_set_irqchip_state(hwirq, which, state)
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_ipi_send_single(hwirq: u32, cpu: moana::bsp::smp::CpuId) {
                BSP_IRQCHIP.ipi_send_single(hwirq, cpu);
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_ipi_send_mask(hwirq: u32, cpumask: &moana::bsp::smp::Cpumask) {
                BSP_IRQCHIP.ipi_send_mask(hwirq, cpumask);
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_handler() {
                BSP_IRQCHIP.irq_handler();
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_init() {
                BSP_IRQCHIP.irq_init();
            }

            #[unsafe(no_mangle)]
            fn bsp_irqchip_irq_init_cpu() {
                BSP_IRQCHIP.irq_init_cpu();
            }

            // ---- 时钟 ----
            static BSP_CLOCK: Clock =
                <#ty as moana::bsp::BspDefine>::DEFINE_CLOCK;

            #[unsafe(no_mangle)]
            fn bsp_clock_init() {
                BSP_CLOCK.init();
            }

            #[unsafe(no_mangle)]
            fn bsp_clock_init_cpu() {
                BSP_CLOCK.init_cpu();
            }

            #[unsafe(no_mangle)]
            fn bsp_clock_get_set_next_event() -> moana::bsp::clocksource::SetNextEventFunc {
                BSP_CLOCK.get_set_next_event()
            }

            #[unsafe(no_mangle)]
            fn bsp_clock_get_set_state_stopped() -> moana::bsp::clocksource::SetStateStoppedFunc {
                BSP_CLOCK.get_set_state_stopped()
            }

            #[unsafe(no_mangle)]
            fn bsp_clock_rate() -> usize {
                BSP_CLOCK.rate()
            }

            #[unsafe(no_mangle)]
            fn bsp_clock_min_delta() -> u64 {
                BSP_CLOCK.min_delta()
            }

            #[unsafe(no_mangle)]
            fn bsp_clock_max_delta() -> u64 {
                BSP_CLOCK.max_delta()
            }
        };
    )
    .into()
}
