///|
pub(all) enum Orientation {
  Horizontal
  Vertical
}

///|
fn Orientation::to_gtk(self : Orientation) -> @gtk.Orientation {
  match self {
    Horizontal => Horizontal
    Vertical => Vertical
  }
}

///|
pub(all) enum Align {
  Fill
  Start
  End
  Center
}

///|
fn Align::to_gtk(self : Align) -> @gtk.Align {
  match self {
    Fill => Fill
    Start => Start
    End => End
    Center => Center
  }
}

///|
enum VWidget[Message] {
  Window(
    title~ : String,
    default_width~ : Int,
    default_height~ : Int,
    child~ : VWidget[Message]
  )
  Box(
    orientation~ : Orientation,
    spacing~ : Int,
    margin_top~ : Int,
    margin_bottom~ : Int,
    margin_start~ : Int,
    margin_end~ : Int,
    halign~ : Align?,
    css_classes~ : Array[String],
    children~ : Array[VWidget[Message]]
  )
  Button(
    label~ : String,
    icon_name~ : String,
    css_classes~ : Array[String],
    on_clicked~ : Message
  )
  Label(
    text~ : String,
    markup~ : Bool,
    wrap~ : Bool,
    selectable~ : Bool,
    xalign~ : Double,
    max_width_chars~ : Int,
    css_classes~ : Array[String]
  )
  Entry(
    text~ : String,
    placeholder~ : String,
    hexpand~ : Bool,
    on_changed~ : (String) -> Message,
    on_activate~ : Message?
  )
  AdwApplicationWindow(
    title~ : String,
    default_width~ : Int,
    default_height~ : Int,
    content~ : VWidget[Message]
  )
  AdwToolbarView(
    top_bar~ : VWidget[Message]?,
    bottom_bar~ : VWidget[Message]?,
    content~ : VWidget[Message]
  )
  AdwHeaderBar(
    title_widget~ : VWidget[Message]?,
    start~ : Array[VWidget[Message]],
    end~ : Array[VWidget[Message]]
  )
  ScrolledWindow(
    hscrollbar_policy~ : @gtk.PolicyType,
    vscrollbar_policy~ : @gtk.PolicyType,
    vexpand~ : Bool,
    child~ : VWidget[Message]
  )
  ListBox(
    css_classes~ : Array[String],
    children~ : Map[String, VWidget[Message]]
  )
  CheckButton(active~ : Bool, on_toggled~ : (Bool) -> Message)
  AdwClamp(maximum_size~ : Int, child~ : VWidget[Message])
  AdwActionRow(
    title~ : String,
    subtitle~ : String,
    prefix~ : Array[VWidget[Message]],
    suffix~ : Array[VWidget[Message]]
  )
  Separator(orientation~ : Orientation)
  AdwNavigationSplitView(
    sidebar~ : VWidget[Message],
    sidebar_title~ : String,
    content~ : VWidget[Message],
    content_title~ : String,
    min_sidebar_width~ : Double,
    max_sidebar_width~ : Double,
    sidebar_width_fraction~ : Double
  )
}

///|
pub fn[Message] window(
  title? : String = "",
  default_width? : Int = 400,
  default_height? : Int = 300,
  child : VWidget[Message],
) -> VWidget[Message] {
  Window(title~, default_width~, default_height~, child~)
}

///|
pub fn[Message] box(
  orientation? : Orientation = Vertical,
  spacing? : Int = 0,
  margin? : Int = 0,
  margin_top? : Int,
  margin_bottom? : Int,
  margin_start? : Int,
  margin_end? : Int,
  halign? : Align,
  css_classes? : Array[String] = [],
  children : Array[VWidget[Message]],
) -> VWidget[Message] {
  Box(
    orientation~,
    spacing~,
    margin_top=margin_top.unwrap_or(margin),
    margin_bottom=margin_bottom.unwrap_or(margin),
    margin_start=margin_start.unwrap_or(margin),
    margin_end=margin_end.unwrap_or(margin),
    halign~,
    css_classes~,
    children~,
  )
}

///|
pub fn[Message] button(
  label? : String = "",
  icon_name? : String = "",
  css_classes? : Array[String] = [],
  on_clicked~ : Message,
) -> VWidget[Message] {
  Button(label~, icon_name~, css_classes~, on_clicked~)
}

///|
pub fn[Message] label(
  text? : String = "",
  markup? : Bool = false,
  wrap? : Bool = false,
  selectable? : Bool = false,
  xalign? : Double = 0.5,
  max_width_chars? : Int = -1,
  css_classes? : Array[String] = [],
) -> VWidget[Message] {
  Label(
    text~,
    markup~,
    wrap~,
    selectable~,
    xalign~,
    max_width_chars~,
    css_classes~,
  )
}

///|
pub fn[Message] entry(
  text? : String = "",
  placeholder? : String = "",
  hexpand? : Bool = false,
  on_changed~ : (String) -> Message,
  on_activate? : Message,
) -> VWidget[Message] {
  Entry(text~, placeholder~, hexpand~, on_changed~, on_activate~)
}

///|
pub fn[Message] adw_application_window(
  title? : String = "",
  default_width? : Int = 400,
  default_height? : Int = 300,
  content : VWidget[Message],
) -> VWidget[Message] {
  AdwApplicationWindow(title~, default_width~, default_height~, content~)
}

///|
pub fn[Message] adw_toolbar_view(
  top_bar? : VWidget[Message],
  bottom_bar? : VWidget[Message],
  content : VWidget[Message],
) -> VWidget[Message] {
  AdwToolbarView(top_bar~, bottom_bar~, content~)
}

///|
pub fn[Message] adw_header_bar(
  title_widget? : VWidget[Message],
  start? : Array[VWidget[Message]] = [],
  end? : Array[VWidget[Message]] = [],
) -> VWidget[Message] {
  AdwHeaderBar(title_widget~, start~, end~)
}

///|
pub fn[Message] scrolled_window(
  hscrollbar_policy? : @gtk.PolicyType = @gtk.PolicyType::Automatic,
  vscrollbar_policy? : @gtk.PolicyType = @gtk.PolicyType::Automatic,
  vexpand? : Bool = false,
  child : VWidget[Message],
) -> VWidget[Message] {
  ScrolledWindow(hscrollbar_policy~, vscrollbar_policy~, vexpand~, child~)
}

///|
pub fn[Message] separator(
  orientation? : Orientation = Horizontal,
) -> VWidget[Message] {
  Separator(orientation~)
}

///|
pub fn[Message] adw_navigation_split_view(
  sidebar~ : VWidget[Message],
  sidebar_title? : String = "",
  content~ : VWidget[Message],
  content_title? : String = "",
  min_sidebar_width? : Double = 180.0,
  max_sidebar_width? : Double = 280.0,
  sidebar_width_fraction? : Double = 0.25,
) -> VWidget[Message] {
  AdwNavigationSplitView(
    sidebar~,
    sidebar_title~,
    content~,
    content_title~,
    min_sidebar_width~,
    max_sidebar_width~,
    sidebar_width_fraction~,
  )
}

///|
pub fn[Message] list_box(
  css_classes? : Array[String] = [],
  children : Map[String, VWidget[Message]],
) -> VWidget[Message] {
  ListBox(css_classes~, children~)
}

///|
pub fn[Message] check_button(
  active? : Bool = false,
  on_toggled~ : (Bool) -> Message,
) -> VWidget[Message] {
  CheckButton(active~, on_toggled~)
}

///|
pub fn[Message] adw_clamp(
  maximum_size? : Int = 600,
  child : VWidget[Message],
) -> VWidget[Message] {
  AdwClamp(maximum_size~, child~)
}

///|
pub fn[Message] adw_action_row(
  title? : String = "",
  subtitle? : String = "",
  prefix? : Array[VWidget[Message]] = [],
  suffix? : Array[VWidget[Message]] = [],
) -> VWidget[Message] {
  AdwActionRow(title~, subtitle~, prefix~, suffix~)
}