use alloc::{sync::Arc, vec::Vec};
use device_api::interrupt::{InterruptHandler, IrqVector};
use libk_util::sync::spin_rwlock::IrqSafeRwLock;

pub struct FixedInterruptTable {
    rows: Vec<IrqSafeRwLock<Vec<Arc<dyn InterruptHandler>>>>,
}

impl FixedInterruptTable {
    pub fn new(irq_lines: usize) -> Self {
        Self {
            rows: (0..irq_lines)
                .map(|_| IrqSafeRwLock::new(Vec::new()))
                .collect(),
        }
    }

    pub fn insert(&self, line: usize, handler: Arc<dyn InterruptHandler>) {
        let mut row = self.rows[line].write();
        row.push(handler);
    }

    pub fn insert_least_loaded(&self, handler: Arc<dyn InterruptHandler>) -> usize {
        let min_line = self
            .rows
            .iter()
            .enumerate()
            .min_by_key(|(_, row)| row.read().len())
            .unwrap()
            .0;
        self.insert(min_line, handler);
        min_line
    }

    pub fn handle_irq_line(&self, line: usize, vector: IrqVector) -> bool {
        let row = self.rows[line].read();
        for handler in row.iter() {
            if handler.clone().handle_irq(vector) {
                return true;
            }
        }
        false
    }
}
