use crate::model::{Alignment, DecorationStyle, Margins, Style, TextDecoration};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ResolvedStyle {
    pub font_size: f32,
    pub bold: bool,
    pub italics: bool,
    pub font_family: Option<String>,
    pub line_height: f32,
    pub alignment: 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: bool,
    pub unbreakable: bool,
    pub sup: bool,
    pub sub: bool,
    pub word_break: Option<String>,
    pub leading_indent: f32,
    pub preserve_leading_spaces: bool,
    pub preserve_trailing_spaces: bool,
    pub font_features: Option<Vec<String>>,
    pub overlay_pattern: Option<String>,
    pub overlay_opacity: Option<f32>,
}

impl From<&Style> for ResolvedStyle {
    fn from(style: &Style) -> Self {
        Self {
            font_size: style.font_size.unwrap_or(12.0),
            bold: style.bold.unwrap_or(false),
            italics: style.italics.unwrap_or(false),
            font_family: style.font_family.clone(),
            line_height: style.line_height.unwrap_or(1.0),
            alignment: style.alignment.unwrap_or(Alignment::Left),
            decoration: style.decoration,
            color: style.color.clone(),
            background: style.background.clone(),
            margin: style.margin,
            fill_color: style.fill_color.clone(),
            fill_opacity: style.fill_opacity,
            opacity: style.opacity,
            decoration_style: style.decoration_style,
            decoration_color: style.decoration_color.clone(),
            decoration_thickness: style.decoration_thickness,
            link: style.link.clone(),
            border_color: style.border_color.clone(),
            character_spacing: style.character_spacing,
            no_wrap: style.no_wrap.unwrap_or(false),
            unbreakable: style.unbreakable.unwrap_or(false),
            sup: style.sup.unwrap_or(false),
            sub: style.sub.unwrap_or(false),
            word_break: style.word_break.clone(),
            leading_indent: style.leading_indent.unwrap_or(0.0),
            preserve_leading_spaces: style.preserve_leading_spaces.unwrap_or(false),
            preserve_trailing_spaces: style.preserve_trailing_spaces.unwrap_or(false),
            font_features: style.font_features.clone(),
            overlay_pattern: style.overlay_pattern.clone(),
            overlay_opacity: style.overlay_opacity,
        }
    }
}

impl ResolvedStyle {
    pub fn merge_style(mut self, style: &Style) -> Self {
        if let Some(value) = style.font_size {
            self.font_size = value;
        }
        if let Some(value) = style.bold {
            self.bold = value;
        }
        if let Some(value) = style.italics {
            self.italics = value;
        }
        if let Some(value) = &style.font_family {
            self.font_family = Some(value.clone());
        }
        if let Some(value) = style.line_height {
            self.line_height = value;
        }
        if let Some(value) = style.alignment {
            self.alignment = value;
        }
        if let Some(value) = style.decoration {
            self.decoration = Some(value);
        }
        if let Some(value) = &style.color {
            self.color = Some(value.clone());
        }
        if let Some(value) = &style.background {
            self.background = Some(value.clone());
        }
        if let Some(value) = style.margin {
            self.margin = Some(value);
        }
        if let Some(value) = &style.fill_color {
            self.fill_color = Some(value.clone());
        }
        if let Some(value) = style.fill_opacity {
            self.fill_opacity = Some(value);
        }
        if let Some(value) = style.opacity {
            self.opacity = Some(value);
        }
        if let Some(value) = style.decoration_style {
            self.decoration_style = Some(value);
        }
        if let Some(value) = &style.decoration_color {
            self.decoration_color = Some(value.clone());
        }
        if let Some(value) = style.decoration_thickness {
            self.decoration_thickness = Some(value);
        }
        if let Some(value) = &style.link {
            self.link = Some(value.clone());
        }
        if let Some(value) = &style.border_color {
            self.border_color = Some(value.clone());
        }
        if let Some(value) = style.character_spacing {
            self.character_spacing = Some(value);
        }
        if let Some(value) = style.no_wrap {
            self.no_wrap = value;
        }
        if let Some(value) = style.unbreakable {
            self.unbreakable = value;
        }
        if let Some(value) = style.sup {
            self.sup = value;
        }
        if let Some(value) = style.sub {
            self.sub = value;
        }
        if let Some(value) = &style.word_break {
            self.word_break = Some(value.clone());
        }
        if let Some(value) = &style.overlay_pattern {
            self.overlay_pattern = Some(value.clone());
        }
        if let Some(value) = style.overlay_opacity {
            self.overlay_opacity = Some(value);
        }
        if let Some(value) = style.leading_indent {
            self.leading_indent = value;
        }
        if let Some(value) = style.preserve_leading_spaces {
            self.preserve_leading_spaces = value;
        }
        if let Some(value) = style.preserve_trailing_spaces {
            self.preserve_trailing_spaces = value;
        }
        if let Some(value) = &style.font_features {
            self.font_features = Some(value.clone());
        }
        self
    }
}
