use std::sync::Arc;

use core_affinity::CoreId;
use crossbeam::atomic::AtomicCell;

use super::TaskExecutor;

/// Simple thread pool
/// Used for quickly submitting tasks
/// Only one thread, bound to only one core
/// 简易线程池
/// 用于快速提交任务
/// 只有一个线程, 只绑定一个核心
pub struct ThreadPoolConstNum<const N: usize> {
    thread: [TaskExecutor; N],
    cur_run_core: AtomicCell<usize>,
}

impl<const N: usize> ThreadPoolConstNum<N> {
    pub fn new() -> Self {
        // Use use_last_core2 to get the specified number of CPU cores
        // 使用 use_last_core2 获取指定数量的 CPU 核心
        let use_cores = super::use_last_core2("ThreadPoolConstNum", N);

        // Create thread executors
        // 创建线程执行器
        let mut threads = vec![];
        for core_id in &use_cores {
            threads.push(TaskExecutor::new(CoreId { id: *core_id }, 49));
        }

        ThreadPoolConstNum {
            thread: threads
                .try_into()
                .expect("ThreadPoolLiteNum threads.try_into()"),
            cur_run_core: 0.into(),
        }
    }

    pub fn spawn<F>(&self, f: F)
    where
        F: FnOnce(),
        F: Send + 'static,
    {
        let cur_index = self.cur_run_core.fetch_add(1);
        self.thread[cur_index % N].spawn(|_| f());
        if cur_index >= usize::MAX - N {
            self.cur_run_core.store(0);
        }
    }

    pub fn spawn_with_idx<F>(&self, f: F, thread_idx: usize)
    where
        F: FnOnce(),
        F: Send + 'static,
    {
        self.thread[thread_idx].spawn(|_| f());
        self.cur_run_core.store(thread_idx);
    }

    pub fn thread_count(&self) -> usize {
        N
    }
}

pub fn _test_ThreadPoolConstNum(test_count: u128) {
    println!("------------------------start------------------------");
    // println!("1%3: {}", 1 % 3);
    // println!("2%3: {}", 2 % 3);
    // println!("3%3: {}", 3 % 3);
    // println!("4%3: {}", 4 % 3);
    // println!("5%3: {}", 5 % 3);
    // println!("6%3: {}", 6 % 3);
    // println!("7%3: {}", 7 % 3);
    // println!("8%3: {}", 8 % 3);

    let pool = ThreadPoolConstNum::<5>::new();
    std::thread::sleep(std::time::Duration::from_millis(200));
    let com_time = Arc::new(AtomicCell::new(0_u128));
    for _ in 0..test_count {
        let com_time = com_time.clone();
        let now = std::time::Instant::now();
        pool.spawn(move || {
            // println!("run _test_cur_index i: {}", i);
            com_time.fetch_add(now.elapsed().as_nanos());
        });
    }
    println!("------------------------ThreadPoolConstNum 任务提交完成------------------------");
    std::thread::sleep(std::time::Duration::from_secs(1));
    println!(
        "ThreadPoolConstNum 线程开启平均耗时: {} ns",
        com_time.load() as f64 / test_count as f64
    );
}
