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

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

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

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

impl TypeRole {
    pub const fn size(self) -> f32 {
        match self {
            Self::Caption | Self::Eyebrow => 9.0,
            Self::Small => 10.0,
            Self::Body => 11.0,
            Self::Control | Self::AssetLabel => 10.0,
            Self::Section => 11.0,
            Self::AssetTitle => 13.0,
            Self::Title => 14.0,
        }
    }

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

    pub 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 fn text(self, value: impl Into<String>) -> RichText {
        RichText::new(value).font(self.font())
    }
}

pub 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::Eyebrow.size(), 9.0);
        assert_eq!(TypeRole::Small.size(), 10.0);
        assert_eq!(TypeRole::Body.size(), 11.0);
        assert_eq!(TypeRole::Control.size(), 10.0);
        assert_eq!(TypeRole::Section.size(), 11.0);
        assert_eq!(TypeRole::AssetLabel.size(), 10.0);
        assert_eq!(TypeRole::AssetTitle.size(), 13.0);
        assert_eq!(TypeRole::Title.size(), 14.0);
        assert!(!TypeRole::Body.bold());
        assert!(TypeRole::Eyebrow.bold());
        assert!(TypeRole::Section.bold());
        assert!(TypeRole::AssetLabel.bold());
        assert!(TypeRole::AssetTitle.bold());
    }
}
