use core::panic::PanicInfo;

use kernel_arch::{Architecture, ArchitectureImpl};
use libk_util::OneTimeInit;

static PANIC_HANDLER: OneTimeInit<fn(&PanicInfo) -> !> = OneTimeInit::new();

pub fn set_handler(handler: fn(&PanicInfo) -> !) {
    PANIC_HANDLER.init(handler);
}

#[panic_handler]
fn panic_handler(pi: &core::panic::PanicInfo) -> ! {
    if let Some(ph) = PANIC_HANDLER.try_get() {
        ph(pi);
    } else {
        log::error!("Kernel panic: {}", pi.message());
        if let Some(location) = pi.location() {
            log::error!("   at {location}");
        }

        loop {
            unsafe {
                ArchitectureImpl::set_interrupt_mask(true);
            }
            ArchitectureImpl::wait_for_interrupt();
        }
    }
}
