//! Source Sans typography roles used by the Penpot-led editor visual system.

use bevy_egui::egui::{self, FontFamily, FontId, RichText, Style, TextStyle};

use crate::ui::fonts::{SOURCE_SANS_BOLD, SOURCE_SANS_REGULAR};

#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) enum TypeRole {
    Caption,
    Small,
    Body,
    Control,
    Section,
    Title,
}

impl TypeRole {
    pub(crate) const fn size(self) -> f32 {
        match self {
            Self::Caption => 9.0,
            Self::Small => 10.0,
            Self::Body => 11.0,
            Self::Control => 12.0,
            Self::Section => 12.0,
            Self::Title => 16.0,
        }
    }

    pub(crate) const fn bold(self) -> bool {
        matches!(self, Self::Section | Self::Title)
    }

    pub(crate) fn font(self) -> FontId {
        let family = if self.bold() {
            SOURCE_SANS_BOLD
        } else {
            SOURCE_SANS_REGULAR
        };
        FontId::new(self.size(), FontFamily::Name(family.into()))
    }

    pub(crate) fn text(self, value: impl Into<String>) -> RichText {
        RichText::new(value).font(self.font())
    }
}

pub(crate) fn install_local_text_styles(style: &mut Style) {
    style
        .text_styles
        .insert(TextStyle::Body, TypeRole::Body.font());
    style
        .text_styles
        .insert(TextStyle::Button, TypeRole::Control.font());
    style
        .text_styles
        .insert(TextStyle::Small, TypeRole::Small.font());
    style
        .text_styles
        .insert(TextStyle::Heading, TypeRole::Title.font());
    style.text_styles.insert(
        TextStyle::Monospace,
        FontId::new(11.0, egui::FontFamily::Monospace),
    );
}

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

    #[test]
    fn penpot_type_scale_and_weights_are_stable() {
        assert_eq!(TypeRole::Caption.size(), 9.0);
        assert_eq!(TypeRole::Small.size(), 10.0);
        assert_eq!(TypeRole::Body.size(), 11.0);
        assert_eq!(TypeRole::Section.size(), 12.0);
        assert_eq!(TypeRole::Title.size(), 16.0);
        assert!(!TypeRole::Body.bold());
        assert!(TypeRole::Section.bold());
    }
}
