use gtk4 as gtk;

use gtk::builders::*;
use gtk::Align;

/**
 * Types
 */

pub type Margin = (i32, i32, i32, i32);

/**
 * Enums
 */

pub enum MarginData {
    EqualsMargin(i32),
    MultipleMargin(Margin),
}

/**
 * Structs
 */

#[allow(dead_code)]
pub struct Size {
    pub width: i32,
    pub height: i32,
}

#[derive(Copy, Clone)]
pub struct Alignment {
    pub horizontal: Align,
    pub vertical: Align,
}

/**
 * Traits
 */

pub trait Setters {
    fn set_margin(self, margin: MarginData) -> Self;
    fn set_align(self, align: Alignment) -> Self;
}

/**
 * Macros
 */

macro_rules! impl_setters {
    ($($t:ty),+) => {
        $(
            impl Setters for $t {
                fn set_margin(self, margin: MarginData) -> Self {
                    match margin{
                        MarginData::EqualsMargin(margin) =>
                            self.margin_top(margin)
                                .margin_start(margin)
                                .margin_bottom(margin)
                                .margin_end(margin),
                        MarginData::MultipleMargin(margins) =>
                            self.margin_top(margins.0)
                                .margin_start(margins.1)
                                .margin_bottom(margins.2)
                                .margin_end(margins.3),
                    }
                }
                fn set_align(self, align: Alignment) -> Self {
                    self.halign(align.horizontal)
                        .valign(align.vertical)
                }
            }
        )*
    }
}

impl_setters! {ButtonBuilder, EntryBuilder, TextViewBuilder,
BoxBuilder, SwitchBuilder, FrameBuilder, LabelBuilder}

#[allow(dead_code)]
impl Size {
    pub fn new(w: i32, h: i32) -> Size {
        Size {
            width: w,
            height: h,
        }
    }
}

impl Alignment {
    pub fn new(horizontal: Align, vertical: Align) -> Alignment {
        Alignment {
            horizontal,
            vertical,
        }
    }
}