use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CompressionLevel {
    None,
    Fast,
    Default,
    Best,
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum Alignment {
    Left,
    Center,
    Right,
    Justify,
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum VerticalAlignment {
    Top,
    Middle,
    Bottom,
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum PageBreakMode {
    Before,
    After,
    BeforeOdd,
    BeforeEven,
    AfterOdd,
    AfterEven,
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum TextDecoration {
    Underline,
    Strikethrough,
    Overline,
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum DecorationStyle {
    Solid,
    Double,
    Dashed,
    Dotted,
    Wavy,
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Margins {
    pub left: f32,
    pub top: f32,
    pub right: f32,
    pub bottom: f32,
}

impl Margins {
    pub fn all(value: f32) -> Self {
        Self { left: value, top: value, right: value, bottom: value }
    }

    pub fn new(left: f32, top: f32, right: f32, bottom: f32) -> Self {
        Self { left, top, right, bottom }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct PageSize {
    pub width: f32,
    pub height: f32,
    pub auto_height: bool,
}

impl PageSize {
    pub fn new(width: f32, height: f32) -> Self {
        Self { width, height, auto_height: false }
    }

    pub fn auto_width(width: f32) -> Self {
        Self { width, height: 841.89, auto_height: true }
    }

    pub fn a0() -> Self { Self { width: 2383.94, height: 3370.39, auto_height: false } }
    pub fn a1() -> Self { Self { width: 1683.78, height: 2383.94, auto_height: false } }
    pub fn a2() -> Self { Self { width: 1190.55, height: 1683.78, auto_height: false } }
    pub fn a3() -> Self { Self { width: 841.89, height: 1190.55, auto_height: false } }
    pub fn a4() -> Self { Self { width: 595.28, height: 841.89, auto_height: false } }
    pub fn a5() -> Self { Self { width: 419.53, height: 595.28, auto_height: false } }
    pub fn a6() -> Self { Self { width: 297.64, height: 419.53, auto_height: false } }
    pub fn a7() -> Self { Self { width: 209.76, height: 297.64, auto_height: false } }
    pub fn a8() -> Self { Self { width: 147.40, height: 209.76, auto_height: false } }
    pub fn a9() -> Self { Self { width: 104.88, height: 147.40, auto_height: false } }
    pub fn a10() -> Self { Self { width: 73.70, height: 104.88, auto_height: false } }

    pub fn b0() -> Self { Self { width: 2834.65, height: 4008.19, auto_height: false } }
    pub fn b1() -> Self { Self { width: 2004.09, height: 2834.65, auto_height: false } }
    pub fn b2() -> Self { Self { width: 1417.32, height: 2004.09, auto_height: false } }
    pub fn b3() -> Self { Self { width: 1000.63, height: 1417.32, auto_height: false } }
    pub fn b4() -> Self { Self { width: 708.66, height: 1000.63, auto_height: false } }
    pub fn b5() -> Self { Self { width: 498.90, height: 708.66, auto_height: false } }
    pub fn b6() -> Self { Self { width: 354.33, height: 498.90, auto_height: false } }
    pub fn b7() -> Self { Self { width: 249.45, height: 354.33, auto_height: false } }
    pub fn b8() -> Self { Self { width: 175.75, height: 249.45, auto_height: false } }
    pub fn b9() -> Self { Self { width: 124.72, height: 175.75, auto_height: false } }
    pub fn b10() -> Self { Self { width: 87.87, height: 124.72, auto_height: false } }

    pub fn letter() -> Self { Self { width: 612.0, height: 792.0, auto_height: false } }
    pub fn legal() -> Self { Self { width: 612.0, height: 1008.0, auto_height: false } }
    pub fn tabloid() -> Self { Self { width: 792.0, height: 1224.0, auto_height: false } }
    pub fn executive() -> Self { Self { width: 521.86, height: 756.0, auto_height: false } }

    pub fn landscape(mut self) -> Self {
        if self.width < self.height {
            std::mem::swap(&mut self.width, &mut self.height);
        }
        self
    }

    pub fn portrait(mut self) -> Self {
        if self.width > self.height {
            std::mem::swap(&mut self.width, &mut self.height);
        }
        self
    }

    pub fn is_landscape(&self) -> bool {
        self.width > self.height
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum TableWidth {
    Auto,
    Star,
    Fixed(f32),
}

#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum TableStyle {
    NoBorders,
    HeaderLineOnly,
    LightHorizontalLines,
    LightVerticalLines,
    CrossLines,
}
