//! Unit categories that determine which units can convert to each other.

/// Unit category -- determines which units can convert to each other.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum UnitCategory {
    Length,
    Mass,
    Volume,
    Area,
    Speed,
    Temperature,
    Data,
    Angle,
    Time,
    Pressure,
    Energy,
    Power,
    Force,
    CssScreen,
}

impl UnitCategory {
    /// Return all standard categories (excludes CssScreen which is special).
    pub fn all() -> &'static [UnitCategory] {
        &[
            UnitCategory::Length,
            UnitCategory::Mass,
            UnitCategory::Volume,
            UnitCategory::Area,
            UnitCategory::Speed,
            UnitCategory::Temperature,
            UnitCategory::Data,
            UnitCategory::Angle,
            UnitCategory::Time,
            UnitCategory::Pressure,
            UnitCategory::Energy,
            UnitCategory::Power,
            UnitCategory::Force,
            UnitCategory::CssScreen,
        ]
    }

    pub fn name(&self) -> &'static str {
        match self {
            UnitCategory::Length => "length",
            UnitCategory::Mass => "mass",
            UnitCategory::Volume => "volume",
            UnitCategory::Area => "area",
            UnitCategory::Speed => "speed",
            UnitCategory::Temperature => "temperature",
            UnitCategory::Data => "data",
            UnitCategory::Angle => "angle",
            UnitCategory::Time => "time",
            UnitCategory::Pressure => "pressure",
            UnitCategory::Energy => "energy",
            UnitCategory::Power => "power",
            UnitCategory::Force => "force",
            UnitCategory::CssScreen => "css/screen",
        }
    }
}

impl std::fmt::Display for UnitCategory {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.name())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_all_returns_14_categories() {
        assert_eq!(UnitCategory::all().len(), 14);
    }

    #[test]
    fn test_category_names_are_unique() {
        let names: Vec<&str> = UnitCategory::all().iter().map(|c| c.name()).collect();
        let mut deduped = names.clone();
        deduped.sort();
        deduped.dedup();
        assert_eq!(names.len(), deduped.len(), "Category names must be unique");
    }

    #[test]
    fn test_display_matches_name() {
        for cat in UnitCategory::all() {
            assert_eq!(format!("{}", cat), cat.name());
        }
    }
}
