mod color;
mod dim;
mod elevation;
mod motion;
mod scales;
mod typography;

pub use color::{CadColors, Color, ColorError, Colors, Scale12, Step12, SurfaceLevel};
pub use dim::{BlurRadius, Radius, ShadowOffset, Spacing, StrokeWidth};
pub use elevation::{Border, ElevationLevel, ElevationScale, Shadow};
pub use motion::{Easing, Motion, MotionToken};
pub use scales::{RadiusScale, SpacingScale};
pub use typography::{
    FontFace, FontSize, FontWeight, LetterSpacing, LineHeight, Typography, TypographyRole,
};

use serde::{Deserialize, Serialize};

#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum ThemeMode {
    Light,
    Dark,
}

impl core::fmt::Display for ThemeMode {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::Light => f.write_str("light"),
            Self::Dark => f.write_str("dark"),
        }
    }
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Theme {
    pub mode: ThemeMode,
    pub colors: Colors,
    pub cad: CadColors,
    pub spacing: SpacingScale,
    pub typography: Typography,
    pub radius: RadiusScale,
    pub elevation: ElevationScale,
    pub motion: Motion,
}

impl Theme {
    #[must_use]
    pub fn light() -> Self {
        let colors = color::light_colors();
        Self {
            mode: ThemeMode::Light,
            cad: CadColors::classic(),
            spacing: SpacingScale::STANDARD,
            typography: Typography::standard(),
            radius: RadiusScale::STANDARD,
            elevation: ElevationScale::tonal(colors.neutral),
            motion: Motion::STANDARD,
            colors,
        }
    }

    #[must_use]
    pub fn dark() -> Self {
        let colors = color::dark_colors();
        Self {
            mode: ThemeMode::Dark,
            cad: CadColors::classic(),
            spacing: SpacingScale::STANDARD,
            typography: Typography::standard(),
            radius: RadiusScale::STANDARD,
            elevation: ElevationScale::tonal(colors.neutral),
            motion: Motion::STANDARD,
            colors,
        }
    }
}
