pub mod character_devs;
pub mod id;
pub mod pci_inner;

mod dev_vterm;

pub use self::Device::*;

use crate::devices::dev_vterm::VTerm;
use character_devs::{dev_null::DevNull, dev_unicode::DevUnicode, dev_zero::DevZero};
use hashbrown::HashMap;
use kernel::device_interface::character::CharacterDevice;
use spin::Lazy;

pub static DEVICE_TABLE: Lazy<spin::Mutex<DeviceTable>> =
    Lazy::new(|| spin::Mutex::new(DeviceTable::new()));

// FIXME: This is a hack to hold a device.
// #[derive(Debug)]
pub enum Device {
    Character(Box<dyn CharacterDevice>),
    Vterm(Box<VTerm>),
}

unsafe impl Sync for Device {}
unsafe impl Send for Device {}

pub struct DeviceTable {
    pub devices: HashMap<String, Device>,
}

impl DeviceTable {
    pub fn new() -> Self {
        DeviceTable {
            devices: [
                ("null", Character(Box::new(DevNull))),
                ("zero", Character(Box::new(DevZero))),
                (
                    "unicode",
                    Character(Box::new(DevUnicode {
                        next_write_char: 0x00 as char,
                        next_read_char: 0x00 as char,
                    })),
                ),
                ("kvterm", Vterm(Box::new(VTerm::new()))),
            ]
            .into_iter()
            .map(|(k, v)| (k.to_string(), v))
            .collect(),
        }
    }
}

impl Default for DeviceTable {
    fn default() -> Self {
        Self::new()
    }
}
