//! A tree of hardware devices

use {alloc::vec::Vec, core::fmt, hashbrown::HashMap};

/// A device object.
/// TODO define device
pub type Device = xml::XMLElement;

/// A tree of devices
// TODO: alphabetize this list
#[derive(Debug)]
pub struct DeviceTree<'a> {
    /// The device tree
    pub devices: HashMap<&'a str, Vec<Device>>,
}
impl<'a> DeviceTree<'a> {
    /// Build the device tree. Does not populate the device tree
    pub fn new() -> Self {
        let mut dt = Self {
            devices: HashMap::new(),
        };
        device_tree!(
            dt,
            [
                "Mice",
                "Keyboards",
                "Controllers",
                "Generic HIDs",
                "Disk Drives",
                "CD Drives",
                "Batteries",
                "Monitors",
                "GPUs",
                "CPUs",
                "USB",
                "Serial Ports",
                "Cameras",
                "Biometric Devices",
            ]
        );
        dt
    }
}
use crate::{device_tree, tab, utils::TAB};
impl<'a> fmt::Display for DeviceTree<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f)?;
        for (device_type, devices) in &self.devices {
            writeln!(f, "\r{}{}/\r", tab!(1), device_type)?;
            for device in devices {
                writeln!(f, "{}{}/\r", tab!(2), device.name)?;
                for attr in &device.attributes {
                    writeln!(f, "{}{}\r", tab!(3), attr)?;
                }
                for child in &device.children {
                    writeln!(f, "{}{}\r", tab!(3), child.name)?;
                    for attr in &child.attributes {
                        writeln!(f, "{}{}\r", tab!(4), attr)?;
                    }
                    for child in &child.children {
                        writeln!(f, "{}{}\r", tab!(4), child.name)?;
                        for attr in &child.attributes {
                            writeln!(f, "{}{}\r", tab!(5), attr)?;
                        }
                    }
                }
            }
        }
        Ok(())
    }
}