//! 这个文件内放置初始内核线程的代码。

use core::sync::atomic::{compiler_fence, Ordering};

use alloc::string::{String, ToString};
use log::{debug, error};
use system_error::SystemError;

use crate::{
    arch::{interrupt::TrapFrame, process::arch_switch_to_user},
    driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe},
    filesystem::vfs::core::mount_root_fs,
    net::net_core::net_init,
    process::{kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags, ProcessManager},
    smp::smp_init,
    syscall::Syscall,
};

use super::initcall::do_initcalls;

pub fn initial_kernel_thread() -> i32 {
    kernel_init().unwrap_or_else(|err| {
        panic!("Failed to initialize kernel: {:?}", err);
    });

    switch_to_user();
}

fn kernel_init() -> Result<(), SystemError> {
    KernelThreadMechanism::init_stage2();
    kenrel_init_freeable()?;

    // 由于目前加锁，速度过慢，所以先不开启双缓冲
    // scm_enable_double_buffer().expect("Failed to enable double buffer");

    #[cfg(target_arch = "x86_64")]
    crate::driver::disk::ahci::ahci_init().expect("Failed to initialize AHCI");

    virtio_probe();
    mount_root_fs().expect("Failed to mount root fs");

    e1000e_init();
    net_init().unwrap_or_else(|err| {
        error!("Failed to initialize network: {:?}", err);
    });

    debug!("initial kernel thread done.");

    return Ok(());
}

#[inline(never)]
fn kenrel_init_freeable() -> Result<(), SystemError> {
    do_initcalls().unwrap_or_else(|err| {
        panic!("Failed to initialize subsystems: {:?}", err);
    });
    stdio_init().expect("Failed to initialize stdio");
    smp_init();

    return Ok(());
}

/// 切换到用户态
#[inline(never)]
fn switch_to_user() -> ! {
    let current_pcb = ProcessManager::current_pcb();

    // 删除kthread的标志
    current_pcb.flags().remove(ProcessFlags::KTHREAD);
    current_pcb.worker_private().take();

    *current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;
    drop(current_pcb);

    let mut trap_frame = TrapFrame::new();
    // 逐个尝试运行init进程
    if try_to_run_init_process("/bin/dragonreach", &mut trap_frame).is_err()
        && try_to_run_init_process("/bin/init", &mut trap_frame).is_err()
        && try_to_run_init_process("/bin/sh", &mut trap_frame).is_err()
    {
        panic!("Failed to run init process: No working init found.");
    }

    // 需要确保执行到这里之后，上面所有的资源都已经释放（比如arc之类的）
    compiler_fence(Ordering::SeqCst);

    unsafe { arch_switch_to_user(trap_frame) };
}

fn try_to_run_init_process(path: &str, trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
    if let Err(e) = run_init_process(path.to_string(), trap_frame) {
        if e != SystemError::ENOENT {
            error!(
                "Failed to run init process: {path} exists but couldn't execute it (error {:?})",
                e
            );
        }
        return Err(e);
    }

    Ok(())
}

fn run_init_process(path: String, trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
    let argv = vec![path.clone()];
    let envp = vec![String::from("PATH=/")];

    compiler_fence(Ordering::SeqCst);
    Syscall::do_execve(path, argv, envp, trap_frame)?;

    Ok(())
}
