use alloc::{string::String, sync::Arc, vec::Vec};
use system_error::SystemError;

use crate::{
    arch::reboot::{machine_halt, machine_power_off, machine_restart, migrate_to_reboot_cpu},
    driver::base::device::device_shutdown,
    init::initial_kthread::{set_system_state, SystemState},
    libs::{
        mutex::Mutex,
        notifier::{BlockingNotifierChain, NotifierBlock, SrcuNotifierChain},
        spinlock::SpinLock,
    },
    misc::syscore::syscore_shutdown,
    syscall::user_access::check_and_clone_cstr,
};

static SYSTEM_TRANSITION_MUTEX: Mutex<()> = Mutex::new(());

const LINUX_REBOOT_MAGIC1: u32 = 0xfee1dead;
const LINUX_REBOOT_MAGIC2: u32 = 672274793;
const LINUX_REBOOT_MAGIC2A: u32 = 85072278;
const LINUX_REBOOT_MAGIC2B: u32 = 369367448;
const LINUX_REBOOT_MAGIC2C: u32 = 537993216;

static mut C_A_D: bool = true;
/// Explicitly initialized after the SRCU worker is available. This avoids a
/// fallible lazy allocation first occurring on the shutdown path.
static REBOOT_NOTIFIER_LIST: SpinLock<Option<Arc<SrcuNotifierChain<RebootNotifyEvent, String>>>> =
    SpinLock::new(None);
lazy_static! {
    /// 注册此通知链的回调函数通常是与硬件相关的重启准备处理程序
    static ref RESTART_PERP_HANDLER_LIST: Mutex<BlockingNotifierChain<RebootNotifyEvent, String>> =
        Mutex::new(BlockingNotifierChain::new());
}
lazy_static! {
    /// 注册此通知链的回调函数通常是与硬件相关的重启准备处理程序
    static ref POWER_OFF_PREP_HANDLER_LIST: Mutex<BlockingNotifierChain<RebootNotifyEvent, String>> =
        Mutex::new(BlockingNotifierChain::new());
}
lazy_static! {
    static ref POWER_OFF_HANDLER_LIST: Mutex<Vec<Arc<dyn PowerOffHandler>>> =
        Mutex::new(Vec::new());
}

pub trait PowerOffHandler: Send + Sync {
    fn name(&self) -> &'static str;

    fn priority(&self) -> i32 {
        0
    }

    fn prepare(&self) -> Result<(), SystemError> {
        Ok(())
    }

    /// 成功的关机通常不会返回；如果返回，调用方会将其视为失败并继续尝试后备路径。
    fn power_off(&self) -> Result<(), SystemError>;
}

pub fn register_power_off_handler(handler: Arc<dyn PowerOffHandler>) -> Result<(), SystemError> {
    let mut handlers = POWER_OFF_HANDLER_LIST.lock();

    if handlers
        .iter()
        .any(|existing| Arc::ptr_eq(existing, &handler))
    {
        return Err(SystemError::EEXIST);
    }

    let mut index = 0;
    for existing in handlers.iter() {
        if handler.priority() > existing.priority() {
            break;
        }
        index += 1;
    }

    handlers.insert(index, handler);
    return Ok(());
}

#[allow(dead_code)]
pub fn unregister_power_off_handler(handler: &Arc<dyn PowerOffHandler>) -> Result<(), SystemError> {
    let mut handlers = POWER_OFF_HANDLER_LIST.lock();
    let index = handlers
        .iter()
        .position(|existing| Arc::ptr_eq(existing, handler))
        .ok_or(SystemError::ENOENT)?;
    handlers.remove(index);
    return Ok(());
}

pub fn kernel_can_power_off() -> bool {
    return !POWER_OFF_HANDLER_LIST.lock().is_empty();
}

fn power_off_handlers_snapshot() -> Vec<Arc<dyn PowerOffHandler>> {
    POWER_OFF_HANDLER_LIST.lock().clone()
}

/// # 功能
///
/// 将一个任意实现`NotifierBlock`trait的结构体notifier注册到`REBOOT_NOTIFIER_LIST`通知连中
#[allow(dead_code)]
pub fn register_reboot_notifier(
    notifier: Arc<dyn NotifierBlock<RebootNotifyEvent, String>>,
) -> Result<(), SystemError> {
    let chain = REBOOT_NOTIFIER_LIST
        .lock_irqsave()
        .clone()
        .ok_or(SystemError::ENODEV)?;
    chain.register(notifier)
}

/// # 功能
///
/// 从`REBOOT_NOTIFIER_LIST`通知链中移除指定的实现`NotifierBlock`trait的结构体。
#[allow(dead_code)]
pub fn unregister_reboot_notifier(
    notifier: Arc<dyn NotifierBlock<RebootNotifyEvent, String>>,
) -> Result<(), SystemError> {
    let chain = REBOOT_NOTIFIER_LIST
        .lock_irqsave()
        .clone()
        .ok_or(SystemError::ENODEV)?;
    chain.unregister(notifier)
}

pub fn reboot_notifier_init() -> Result<(), SystemError> {
    let chain = Arc::try_new(SrcuNotifierChain::try_new("reboot_notifier")?)
        .map_err(|_| SystemError::ENOMEM)?;
    let mut slot = REBOOT_NOTIFIER_LIST.lock_irqsave();
    if slot.is_some() {
        return Err(SystemError::EBUSY);
    }
    *slot = Some(chain);
    Ok(())
}

fn reboot_notifier_chain() -> Arc<SrcuNotifierChain<RebootNotifyEvent, String>> {
    REBOOT_NOTIFIER_LIST
        .lock_irqsave()
        .clone()
        .expect("reboot notifier used before initialization")
}

#[derive(Debug)]
pub enum RebootCommand {
    /// 重启系统，使用默认命令和模式
    Restart,
    /// 停止操作系统，并将系统控制权交给ROM监视器（如果有）
    Halt,
    /// Ctrl-Alt-Del序列导致执行RESTART命令
    CadOn,
    /// Ctrl-Alt-Del序列向init任务发送SIGINT信号
    CadOff,
    /// 停止操作系统，如果可能的话从系统中移除所有电源
    PowerOff,
    /// 使用给定的命令字符串重启系统
    Restart2,
    /// 使用软件挂起（如果编译在内）挂起系统
    SoftwareSuspend,
    /// 使用预先加载的Linux内核重启系统
    Kexec,
}

impl TryFrom<u32> for RebootCommand {
    type Error = SystemError;

    fn try_from(value: u32) -> Result<Self, Self::Error> {
        match value {
            0x01234567 => Ok(RebootCommand::Restart),
            0xCDEF0123 => Ok(RebootCommand::Halt),
            0x89ABCDEF => Ok(RebootCommand::CadOn),
            0x00000000 => Ok(RebootCommand::CadOff),
            0x4321FEDC => Ok(RebootCommand::PowerOff),
            0xA1B2C3D4 => Ok(RebootCommand::Restart2),
            0xD000FCE2 => Ok(RebootCommand::SoftwareSuspend),
            0x45584543 => Ok(RebootCommand::Kexec),
            _ => Err(SystemError::EINVAL),
        }
    }
}

impl From<RebootCommand> for u32 {
    fn from(val: RebootCommand) -> Self {
        match val {
            RebootCommand::Restart => 0x01234567,
            RebootCommand::Halt => 0xCDEF0123,
            RebootCommand::CadOn => 0x89ABCDEF,
            RebootCommand::CadOff => 0x00000000,
            RebootCommand::PowerOff => 0x4321FEDC,
            RebootCommand::Restart2 => 0xA1B2C3D4,
            RebootCommand::SoftwareSuspend => 0xD000FCE2,
            RebootCommand::Kexec => 0x45584543,
        }
    }
}

#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
pub enum RebootNotifyEvent {
    /// 系统关闭
    Down,
    /// 系统重启
    Restart,
    /// 系统挂起
    Halt,
    /// 系统关闭电源
    PowerOff,
}

/// 系统调用reboot的实现
///
/// 参考：https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#700
pub(super) fn do_sys_reboot(
    magic1: u32,
    magic2: u32,
    cmd: u32,
    arg: usize,
) -> Result<(), SystemError> {
    if magic1 != LINUX_REBOOT_MAGIC1
        || (magic2 != LINUX_REBOOT_MAGIC2
            && magic2 != LINUX_REBOOT_MAGIC2A
            && magic2 != LINUX_REBOOT_MAGIC2B
            && magic2 != LINUX_REBOOT_MAGIC2C)
    {
        return Err(SystemError::EINVAL);
    }
    let command = RebootCommand::try_from(cmd)?;
    let _guard = SYSTEM_TRANSITION_MUTEX.lock();
    log::debug!(
        "do_sys_reboot: magic1={}, magic2={}, cmd={:?}",
        magic1,
        magic2,
        command
    );
    match command {
        RebootCommand::Restart => kernel_restart(None),
        RebootCommand::Halt => kernel_halt(),
        RebootCommand::CadOn => {
            unsafe {
                C_A_D = true;
            }
            return Ok(());
        }
        RebootCommand::CadOff => {
            unsafe {
                C_A_D = false;
            }
            return Ok(());
        }
        RebootCommand::PowerOff => kernel_power_off(),
        RebootCommand::Restart2 => {
            let s = check_and_clone_cstr(arg as *const u8, Some(256))?;
            let cmd_str = s.to_str().map_err(|_| SystemError::EINVAL)?;
            kernel_restart(Some(cmd_str));
        }
        RebootCommand::SoftwareSuspend => {
            log::warn!("do_sys_reboot: SoftwareSuspend not implemented");
            return Err(SystemError::ENOSYS);
        }
        RebootCommand::Kexec => {
            crate::init::kexec::kexec_core::kernel_kexec();
            return Ok(());
        }
    }
}

/// kernel_restart - 重启系统
///
/// ## 参数
/// - cmd: 指向包含重启命令的缓冲区的指针，或者 None
///
/// 关闭所有东西并执行一个干净的重启。
/// 在中断上下文中调用这是不安全的。
///
/// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#265
pub fn kernel_restart(cmd: Option<&str>) -> ! {
    kernel_restart_prepare(cmd);
    do_kernel_restart_prepare();
    migrate_to_reboot_cpu();
    syscore_shutdown();

    if let Some(cmd) = cmd {
        log::warn!("Restarting system with command: '{}'", cmd);
    } else {
        log::warn!("Restarting system...");
    }

    // 执行与机器硬件相关的重启操作
    machine_restart(cmd);
}

/// # 功能
///
/// 处理一些重启前的准备工作
fn kernel_restart_prepare(cmd: Option<&str>) {
    let cmd = if let Some(cmd) = cmd {
        // 将&str转换为String
        String::from(cmd)
    } else {
        String::new()
    };
    reboot_notifier_chain().call_chain(RebootNotifyEvent::Restart, Some(&cmd), None);

    set_system_state(SystemState::Restart);

    device_shutdown();
}

fn do_kernel_restart_prepare() {
    RESTART_PERP_HANDLER_LIST
        .lock()
        .call_chain(RebootNotifyEvent::Restart, None, None);
}

/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#678
pub fn kernel_power_off() -> ! {
    kernel_shutdown_prepare(SystemState::PowerOff);
    do_kernel_power_off_prepare();
    do_power_off_handlers_prepare();
    migrate_to_reboot_cpu();
    syscore_shutdown();

    log::warn!("Power down");
    machine_power_off();
}

/// # 功能
///
/// 在系统关机前执行必要的准备工作
///
/// 参考: https://elixir.bootlin.com/linux/v6.6/source/kernel/reboot.c#L280
pub fn kernel_shutdown_prepare(state: SystemState) {
    let event = if state == SystemState::Halt {
        RebootNotifyEvent::Halt
    } else {
        RebootNotifyEvent::PowerOff
    };
    reboot_notifier_chain().call_chain(event, None, None);

    set_system_state(state);

    device_shutdown();
}

fn do_kernel_power_off_prepare() {
    POWER_OFF_PREP_HANDLER_LIST
        .lock()
        .call_chain(RebootNotifyEvent::PowerOff, None, None);
}

fn do_power_off_handlers_prepare() {
    if !kernel_can_power_off() {
        log::warn!("kernel_power_off: no power-off handler is registered");
        return;
    }

    let handlers = power_off_handlers_snapshot();
    for handler in handlers {
        if let Err(e) = handler.prepare() {
            log::warn!(
                "kernel_power_off: power-off handler '{}' prepare failed: {:?}",
                handler.name(),
                e
            );
        }
    }
}

pub fn do_machine_power_off() -> Result<(), SystemError> {
    let handlers = power_off_handlers_snapshot();
    if handlers.is_empty() {
        return Err(SystemError::ENODEV);
    }

    let mut last_error = SystemError::ENODEV;
    for handler in handlers {
        match handler.power_off() {
            Ok(()) => {
                log::warn!(
                    "machine_power_off: power-off handler '{}' returned without powering off",
                    handler.name()
                );
                last_error = SystemError::EIO;
            }
            Err(e) => {
                log::warn!(
                    "machine_power_off: power-off handler '{}' failed: {:?}",
                    handler.name(),
                    e
                );
                last_error = e;
            }
        }
    }

    return Err(last_error);
}

/// # 功能
///
/// 执行内核停止操作
///
/// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/kernel/reboot.c#293
pub fn kernel_halt() -> ! {
    kernel_shutdown_prepare(SystemState::Halt);
    migrate_to_reboot_cpu();
    syscore_shutdown();

    machine_halt();
}
