// SPDX-License-Identifier: GPL-3.0-or-later

//! TailwindCSS inspired style definitions.
//!
//! grx components can be styled using the `Style` enum.

#[derive(PartialEq, Debug, Eq, Clone)]
#[allow(non_camel_case_types)]
pub enum Modifier {
    none,
    /// Apply this style when a component is hovered
    hover,
    active,
}
impl Default for Modifier {
    fn default() -> Self {
        Self::none
    }
}

#[derive(PartialEq, Debug, Eq, Clone)]
#[allow(non_camel_case_types)]
pub enum Style {
    none(Modifier),
    bg(Modifier, String),
    /// Margin for all 4 sides.
    m(Modifier, u32),
    mx(Modifier, u32),
    my(Modifier, u32),
    mt(Modifier, u32),
    mb(Modifier, u32),
    ml(Modifier, u32),
    mr(Modifier, u32),
    /// Padding for all 4 sides
    p(Modifier, u32),
    px(Modifier, u32),
    py(Modifier, u32),
    pt(Modifier, u32),
    pb(Modifier, u32),
    pl(Modifier, u32),
    pr(Modifier, u32),

    target(Modifier, bool),

    /// whether a container is layouted vertical
    vertical(Modifier),
    /// whether a container is layouted horizontal
    horizontal(Modifier),
    /// spacing between children of a container
    spacing(Modifier, u32),
    /// How to align an element in relation to its parent
    halign(Modifier, Align),
    /// How to align an element in relation to its parent
    valign(Modifier, Align),

    overflow(Modifier, Overflow),

    text(Modifier, String),
    justify(Modifier, Justify),
    text_size(Modifier, String),
    wrap(Modifier, Wrap),
    selectable(Modifier),
    ellipsize(Modifier, Align),

    vexpand(Modifier),
    hexpand(Modifier),
    homogeneous(Modifier),

    //borders
    border_color(Modifier, String),
    /// border (top, right, bottom, left)
    border(Modifier, u32, u32, u32, u32),
    border_x(Modifier, u32),
    border_y(Modifier, u32),
    border_r(Modifier, u32),
    border_l(Modifier, u32),
    border_t(Modifier, u32),
    border_b(Modifier, u32),

    // The height in pixel
    h(Modifier, u32),
    // The width in pixel
    w(Modifier, u32),

    rounded_full(Modifier),
}

#[cfg(feature = "gtk")]
pub fn apply<C>(style: &Style, component: &std::rc::Rc<C>)
where
    C: crate::ComponentExt + ?Sized,
{
    let inner = component.clone().inner();
    let w: &gtk::Widget = inner.downcast_ref().unwrap();
    Stylable::apply(style, w);
}

pub trait Stylable<T> {
    fn apply(&self, inner: &T);
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Align {
    none,
    start,
    center,
    end,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Justify {
    left,
    right,
    middle,
    fill,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Wrap {
    char,
    word,
    word_char,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Overflow {
    never,
    external,
    horizontal,
    vertical,
    both,
}
