use serde::{Deserialize, Serialize};
use super::{Alignment, DecorationStyle, Margins, TextDecoration};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Style {
    pub font_size: Option<f32>,
    pub bold: Option<bool>,
    pub italics: Option<bool>,
    pub font_family: Option<String>,
    pub line_height: Option<f32>,
    pub alignment: Option<Alignment>,
    pub decoration: Option<TextDecoration>,
    pub color: Option<String>,
    pub background: Option<String>,
    pub margin: Option<Margins>,
    pub fill_color: Option<String>,
    pub fill_opacity: Option<f32>,
    pub opacity: Option<f32>,
    pub decoration_style: Option<DecorationStyle>,
    pub decoration_color: Option<String>,
    pub decoration_thickness: Option<f32>,
    pub link: Option<String>,
    pub border_color: Option<Vec<String>>,
    pub character_spacing: Option<f32>,
    pub no_wrap: Option<bool>,
    pub unbreakable: Option<bool>,
    pub sup: Option<bool>,
    pub sub: Option<bool>,
    pub word_break: Option<String>,
    pub leading_indent: Option<f32>,
    pub preserve_leading_spaces: Option<bool>,
    pub preserve_trailing_spaces: Option<bool>,
    pub font_features: Option<Vec<String>>,
    pub overlay_pattern: Option<String>,
    pub overlay_opacity: Option<f32>,
}

impl Default for Style {
    fn default() -> Self {
        Self { font_size: Some(12.0), bold: Some(false), italics: Some(false), font_family: None, line_height: Some(1.0), alignment: Some(Alignment::Left), decoration: None, color: None, background: None, margin: None, fill_color: None, fill_opacity: None, opacity: None, decoration_style: None, decoration_color: None, decoration_thickness: None, link: None, border_color: None, character_spacing: None, no_wrap: None, unbreakable: None, sup: None, sub: None, word_break: None, leading_indent: None, preserve_leading_spaces: None, preserve_trailing_spaces: None, font_features: None, overlay_pattern: None, overlay_opacity: None }
    }
}

impl Style {
    pub fn new() -> Self {
        Self { font_size: None, bold: None, italics: None, font_family: None, line_height: None, alignment: None, decoration: None, color: None, background: None, margin: None, fill_color: None, fill_opacity: None, opacity: None, decoration_style: None, decoration_color: None, decoration_thickness: None, link: None, border_color: None, character_spacing: None, no_wrap: None, unbreakable: None, sup: None, sub: None, word_break: None, leading_indent: None, preserve_leading_spaces: None, preserve_trailing_spaces: None, font_features: None, overlay_pattern: None, overlay_opacity: None }
    }

    pub fn font_size(mut self, value: f32) -> Self {
        self.font_size = Some(value);
        self
    }

    pub fn bold(mut self, value: bool) -> Self {
        self.bold = Some(value);
        self
    }

    pub fn italics(mut self, value: bool) -> Self {
        self.italics = Some(value);
        self
    }

    pub fn font_family(mut self, value: impl Into<String>) -> Self {
        self.font_family = Some(value.into());
        self
    }

    pub fn line_height(mut self, value: f32) -> Self {
        self.line_height = Some(value);
        self
    }

    pub fn alignment(mut self, value: Alignment) -> Self {
        self.alignment = Some(value);
        self
    }

    pub fn decoration(mut self, value: TextDecoration) -> Self {
        self.decoration = Some(value);
        self
    }

    pub fn color(mut self, value: impl Into<String>) -> Self {
        self.color = Some(value.into());
        self
    }

    pub fn background(mut self, value: impl Into<String>) -> Self {
        self.background = Some(value.into());
        self
    }

    pub fn margin(mut self, value: Margins) -> Self {
        self.margin = Some(value);
        self
    }

    pub fn fill_color(mut self, value: impl Into<String>) -> Self {
        self.fill_color = Some(value.into());
        self
    }

    pub fn fill_opacity(mut self, value: f32) -> Self {
        self.fill_opacity = Some(value);
        self
    }

    pub fn opacity(mut self, value: f32) -> Self {
        self.opacity = Some(value);
        self
    }

    pub fn decoration_style(mut self, value: DecorationStyle) -> Self {
        self.decoration_style = Some(value);
        self
    }

    pub fn decoration_color(mut self, value: impl Into<String>) -> Self {
        self.decoration_color = Some(value.into());
        self
    }

    pub fn decoration_thickness(mut self, value: f32) -> Self {
        self.decoration_thickness = Some(value);
        self
    }

    pub fn link(mut self, url: impl Into<String>) -> Self {
        self.link = Some(url.into());
        self
    }

    pub fn border_color(mut self, colors: Vec<impl Into<String>>) -> Self {
        self.border_color = Some(colors.into_iter().map(|c| c.into()).collect());
        self
    }

    pub fn character_spacing(mut self, value: f32) -> Self {
        self.character_spacing = Some(value);
        self
    }

    pub fn no_wrap(mut self, value: bool) -> Self {
        self.no_wrap = Some(value);
        self
    }

    pub fn unbreakable(mut self, value: bool) -> Self {
        self.unbreakable = Some(value);
        self
    }

    pub fn sup(mut self, value: bool) -> Self {
        self.sup = Some(value);
        self
    }

    pub fn sub(mut self, value: bool) -> Self {
        self.sub = Some(value);
        self
    }

    pub fn word_break(mut self, value: impl Into<String>) -> Self {
        self.word_break = Some(value.into());
        self
    }

    pub fn leading_indent(mut self, value: f32) -> Self {
        self.leading_indent = Some(value);
        self
    }

    pub fn preserve_leading_spaces(mut self, value: bool) -> Self {
        self.preserve_leading_spaces = Some(value);
        self
    }

    pub fn preserve_trailing_spaces(mut self, value: bool) -> Self {
        self.preserve_trailing_spaces = Some(value);
        self
    }

    pub fn font_features(mut self, value: Vec<String>) -> Self {
        self.font_features = Some(value);
        self
    }

    pub fn overlay_pattern(mut self, value: impl Into<String>) -> Self {
        self.overlay_pattern = Some(value.into());
        self
    }

    pub fn overlay_opacity(mut self, value: f32) -> Self {
        self.overlay_opacity = Some(value);
        self
    }

    pub fn has_any(&self) -> bool {
        self.font_size.is_some()
            || self.bold.is_some()
            || self.italics.is_some()
            || self.font_family.is_some()
            || self.line_height.is_some()
            || self.alignment.is_some()
            || self.decoration.is_some()
            || self.color.is_some()
            || self.background.is_some()
            || self.margin.is_some()
            || self.fill_color.is_some()
            || self.fill_opacity.is_some()
            || self.opacity.is_some()
            || self.decoration_style.is_some()
            || self.decoration_color.is_some()
            || self.decoration_thickness.is_some()
            || self.link.is_some()
            || self.border_color.is_some()
            || self.character_spacing.is_some()
            || self.no_wrap.is_some()
            || self.unbreakable.is_some()
            || self.sup.is_some()
            || self.sub.is_some()
            || self.word_break.is_some()
            || self.leading_indent.is_some()
            || self.overlay_pattern.is_some()
            || self.overlay_opacity.is_some()
            || self.preserve_leading_spaces.is_some()
            || self.preserve_trailing_spaces.is_some()
            || self.font_features.is_some()
    }
}
