///|
/// APG Toolbar Pattern
/// https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/
///
/// A toolbar is a container for grouping a set of controls.
///
/// Keyboard Interaction:
/// - Left/Right Arrow (horizontal): Move between items
/// - Up/Down Arrow (vertical): Move between items
/// - Home: Move to first item
/// - End: Move to last item
/// - Tab: Move focus out of toolbar
/// - Enter/Space: Activate button or toggle state
///
/// ARIA:
/// - role="toolbar" on container
/// - aria-orientation (horizontal or vertical)
/// - aria-label or aria-labelledby
/// - Items use roving tabindex

///|
/// Toolbar orientation
pub(all) enum ToolbarOrientation {
  Horizontal
  Vertical
}

///|
/// Create a toolbar container.
///
/// Parameters:
/// - aria_label: Accessible label
/// - aria_labelledby: ID of labelling element
/// - orientation: Toolbar orientation (default: horizontal)
/// - children: Toolbar items
pub fn[E] toolbar(
  aria_label? : String,
  aria_labelledby? : String,
  orientation? : ToolbarOrientation,
  children : Array[@luna.Node[E, String]],
) -> @luna.Node[E, String] {
  let orient = if orientation is Some(Vertical) {
    "vertical"
  } else {
    "horizontal"
  }
  let attrs : Array[(String, @luna.Attr[E, String])] = [
    ("role", @luna.attr_static("toolbar")),
    ("aria-orientation", @luna.attr_static(orient)),
  ]
  if aria_label is Some(label) {
    attrs.push(("aria-label", @luna.attr_static(label)))
  }
  if aria_labelledby is Some(id) {
    attrs.push(("aria-labelledby", @luna.attr_static(id)))
  }
  @luna.h("div", attrs) <| children
}

///|
/// Create a toolbar item (button).
///
/// Parameters:
/// - selected: Whether this item has tabindex=0 (roving tabindex)
/// - pressed: For toggle buttons, the pressed state
/// - disabled: Whether the item is disabled
/// - on_click: Click handler
/// - on_keydown: Keydown handler
/// - children: Button content
pub fn[E] toolbar_item(
  selected : Bool,
  pressed? : Bool,
  disabled? : Bool,
  on_click? : @luna.EventHandler[E],
  on_keydown? : @luna.EventHandler[E],
  children : Array[@luna.Node[E, String]],
) -> @luna.Node[E, String] {
  let is_disabled = disabled.unwrap_or(false)
  let attrs : Array[(String, @luna.Attr[E, String])] = [
    ("type", @luna.attr_static("button")),
    ("tabindex", @luna.attr_static(if selected { "0" } else { "-1" })),
  ]
  if pressed is Some(p) {
    attrs.push(
      ("aria-pressed", @luna.attr_static(if p { "true" } else { "false" })),
    )
  }
  if is_disabled {
    attrs.push(("disabled", @luna.attr_static("")))
    attrs.push(("aria-disabled", @luna.attr_static("true")))
  }
  if on_click is Some(handler) {
    if !is_disabled {
      attrs.push(("click", @luna.attr_handler(handler)))
    }
  }
  if on_keydown is Some(handler) {
    attrs.push(("keydown", @luna.attr_handler(handler)))
  }
  @luna.h("button", attrs) <| children
}

///|
/// Create a dynamic toolbar item with signal-based selection.
pub fn[E] toolbar_item_dyn(
  focused_index : @resource.Signal[Int],
  index : Int,
  pressed? : Bool,
  disabled? : Bool,
  on_click? : @luna.EventHandler[E],
  on_keydown? : @luna.EventHandler[E],
  children : Array[@luna.Node[E, String]],
) -> @luna.Node[E, String] {
  let is_disabled = disabled.unwrap_or(false)
  let attrs : Array[(String, @luna.Attr[E, String])] = [
    ("type", @luna.attr_static("button")),
    (
      "tabindex",
      @luna.attr_dynamic(fn() {
        if focused_index.get() == index {
          "0"
        } else {
          "-1"
        }
      }),
    ),
  ]
  if pressed is Some(p) {
    attrs.push(
      ("aria-pressed", @luna.attr_static(if p { "true" } else { "false" })),
    )
  }
  if is_disabled {
    attrs.push(("disabled", @luna.attr_static("")))
    attrs.push(("aria-disabled", @luna.attr_static("true")))
  }
  if on_click is Some(handler) {
    if !is_disabled {
      attrs.push(("click", @luna.attr_handler(handler)))
    }
  }
  if on_keydown is Some(handler) {
    attrs.push(("keydown", @luna.attr_handler(handler)))
  }
  @luna.h("button", attrs) <| children
}

///|
/// Create a toolbar separator.
/// Separators are purely visual and don't receive focus.
pub fn[E] toolbar_separator(
  orientation? : ToolbarOrientation,
) -> @luna.Node[E, String] {
  // Separator orientation is perpendicular to toolbar orientation
  let orient = match orientation {
    Some(Vertical) => "horizontal"
    _ => "vertical"
  }
  @luna.h(
    "div",
    [
      ("role", @luna.attr_static("separator")),
      ("aria-orientation", @luna.attr_static(orient)),
      ("class", @luna.attr_static("toolbar-separator")),
    ],
  ) <| []
}

///|
/// Create a toolbar keyboard handler.
/// Handles arrow navigation, Home/End.
///
/// Parameters:
/// - current_index: Function returning current focused index
/// - item_count: Total number of focusable items
/// - on_change: Called with new index when focus changes
/// - orientation: Toolbar orientation
/// - focus_item: Function to focus item at index
pub fn make_toolbar_handler(
  current_index : () -> Int,
  item_count : Int,
  on_change : (Int) -> Unit,
  orientation : ToolbarOrientation,
  focus_item : (Int) -> Unit,
) -> @luna.EventHandler[@js.Any] {
  let is_horizontal = match orientation {
    Horizontal => true
    Vertical => false
  }
  @luna.handler(fn(e : @js.Any) {
    let key : String = e._get("key").cast()
    let curr = current_index()
    let next_opt : Int? = if is_horizontal {
      match key {
        "ArrowRight" =>
          if curr < item_count - 1 {
            Some(curr + 1)
          } else {
            None
          }
        "ArrowLeft" => if curr > 0 { Some(curr - 1) } else { None }
        "Home" => Some(0)
        "End" => Some(item_count - 1)
        _ => None
      }
    } else {
      match key {
        "ArrowDown" => if curr < item_count - 1 { Some(curr + 1) } else { None }
        "ArrowUp" => if curr > 0 { Some(curr - 1) } else { None }
        "Home" => Some(0)
        "End" => Some(item_count - 1)
        _ => None
      }
    }
    if next_opt is Some(next) {
      if next != curr {
        let _ = e._call("preventDefault", [])
        on_change(next)
        focus_item(next)
      }
    }
  })
}

///|
/// Toolbar item definition
pub(all) struct ToolbarItemDef {
  id : String
  label : String
  toggle : Bool
  disabled : Bool
}

///|
/// Create a toolbar item definition
pub fn toolbar_item_def(
  id : String,
  label : String,
  toggle? : Bool,
  disabled? : Bool,
) -> ToolbarItemDef {
  {
    id,
    label,
    toggle: toggle.unwrap_or(false),
    disabled: disabled.unwrap_or(false),
  }
}

///|
/// Create an interactive toolbar with keyboard navigation.
///
/// Parameters:
/// - id: Base ID for the toolbar
/// - items: Array of toolbar item definitions
/// - pressed_states: Signal containing map of item ID to pressed state
/// - orientation: Toolbar orientation (default: horizontal)
/// - aria_label: Accessible label
/// - on_item_click: Called when an item is clicked (id, is_toggle)
pub fn toolbar_interactive(
  id : String,
  items : Array[ToolbarItemDef],
  pressed_states : @resource.Signal[Map[String, Bool]],
  orientation? : ToolbarOrientation,
  aria_label? : String,
  on_item_click : (String, Bool) -> Unit,
) -> @luna.Node[@js.Any, String] {
  let orient = orientation.unwrap_or(Horizontal)
  let focused_index = @resource.signal(0)
  let item_count = items.length()
  // Focus helper
  let focus_item = fn(idx : Int) {
    let item_id = id + "-item-" + idx.to_string()
    let doc = @js.global_this()._get("document")
    let el = doc._call("getElementById", [@js.any(item_id)])
    let _ = el._call("focus", [])
  }
  // Keyboard handler
  let keydown_handler = make_toolbar_handler(
    fn() { focused_index.get() },
    item_count,
    fn(idx) { focused_index.set(idx) },
    orient,
    focus_item,
  )
  // Build toolbar items
  let toolbar_items : Array[@luna.Node[@js.Any, String]] = []
  for i, item in items {
    let idx = i
    let item_id = id + "-item-" + i.to_string()
    let is_pressed : Bool? = if item.toggle {
      Some(pressed_states.get().get(item.id).unwrap_or(false))
    } else {
      None
    }
    let attrs : Array[(String, @luna.Attr[@js.Any, String])] = [
      ("type", @luna.attr_static("button")),
      ("id", @luna.attr_static(item_id)),
      (
        "tabindex",
        @luna.attr_dynamic(fn() {
          if focused_index.get() == idx {
            "0"
          } else {
            "-1"
          }
        }),
      ),
      ("keydown", @luna.attr_handler(keydown_handler)),
    ]
    if is_pressed is Some(_) {
      attrs.push(
        (
          "aria-pressed",
          @luna.attr_dynamic(fn() {
            if pressed_states.get().get(item.id).unwrap_or(false) {
              "true"
            } else {
              "false"
            }
          }),
        ),
      )
    }
    if item.disabled {
      attrs.push(("disabled", @luna.attr_static("")))
      attrs.push(("aria-disabled", @luna.attr_static("true")))
    } else {
      attrs.push(
        (
          "click",
          @luna.attr_handler(
            @luna.handler(fn(_) { on_item_click(item.id, item.toggle) }),
          ),
        ),
      )
    }
    toolbar_items.push(
      @luna.h("button", attrs) <| [
        @luna.text(item.label),
      ],
    )
  }
  // Build toolbar container
  let orient_str = match orient {
    Horizontal => "horizontal"
    Vertical => "vertical"
  }
  let container_attrs : Array[(String, @luna.Attr[@js.Any, String])] = [
    ("role", @luna.attr_static("toolbar")),
    ("id", @luna.attr_static(id)),
    ("aria-orientation", @luna.attr_static(orient_str)),
  ]
  if aria_label is Some(label) {
    container_attrs.push(("aria-label", @luna.attr_static(label)))
  }
  @luna.h("div", container_attrs) <| toolbar_items
}