--
-- ItemsList Widget.
-- @copyright Jefferson Gonzalez
-- @license MIT
--
local style = require "core.style"
local Widget = require "widget"
local Button = require "widget.button"
local ListBox = require "widget.listbox"
local InputDialog = require "widget.inputdialog"
local MessageBox = require "widget.messagebox"

---@class widget.itemslist : widget
---@overload fun(parent:widget?):widget.itemslist
---@field list widget.listbox
---@field add widget.button
---@field remove widget.button
local ItemsList = Widget:extend()

---Constructor
---@param parent widget
function ItemsList:new(parent)
  ItemsList.super.new(self, parent)

  self.type_name = "widget.itemslist"

  self.border.width = 0

  self.dialog = false

  self.list = ListBox(self)

  local this = self

  function self.list:on_mouse_pressed(button, x, y, clicks)
    if not ListBox.on_mouse_pressed(self, button, x, y, clicks) then
      return false
    end

    if clicks == 2 and not this.dialog then
      this.dialog = true
      local selected = this.list:get_selected()
      local selvalue = this.list:get_row_text(selected)
      ---@type widget.inputdialog
      local input = InputDialog("Edit Item", "Enter the new item value:", selvalue)
      function input:on_save(value)
        this:edit_item(selected, value)
      end
      function input:on_close()
        InputDialog.on_close(self)
        self:destroy()
        this.dialog = false
      end
      input:show()
    end

    return true
  end

  self.add = Button(self, "Add")
  self.add:set_icon("]")
  function self.add:on_click()
    if not this.dialog then
      ---@type widget.inputdialog
      local input = InputDialog("Add Item", "Enter the new item:")
      function input:on_save(value)
        this:add_item(value)
      end
      function input:on_close()
        InputDialog.on_close(self)
        self:destroy()
        this.dialog = false
      end
      input:show()
    end
  end

  self.remove = Button(self, "Remove")
  self.remove:set_icon("C")
  function self.remove:on_click()
    local selected = this.list:get_selected()
    if selected then
      this:remove_item(selected)
    else
      MessageBox.error("No item selected", "Please select an item to remove")
    end
  end
end

---Add a new item into the list.
---@param text widget.styledtext | string
---@param data any
function ItemsList:add_item(text, data)
  if type(text) == "string" then
    text = {text}
  end
  self.list:add_row(text, data)
  self.list:set_visible_rows()
  self:on_change()
end

---Edit an existing item on the list.
---@param idx integer
---@param text widget.styledtext | string
---@param data any
function ItemsList:edit_item(idx, text, data)
  if type(text) == "string" then
    text = {text}
  end
  self.list:set_row(idx, text)
  if data then
    self.list:set_row_data(idx, data)
  end
  self:on_change()
end

---Remove the given item from the list.
---@param idx integer
function ItemsList:remove_item(idx)
  self.list:remove_row(idx)
  self:on_change()
end

---Return the items from the list.
---@return table<integer, string>
function ItemsList:get_items()
  local output = {}
  local count = #self.list.rows
  for i=1, count, 1 do
    table.insert(output, self.list:get_row_text(i))
  end
  return output
end

function ItemsList:update_size_position()
  ItemsList.super.update_size_position(self)

  local size = self:get_size()

  if self.size.x == 0 then
    size.x = (self.add:get_width()
      + (style.padding.x / 2) + self.remove:get_width() + (100 * SCALE)
    )
  end

  self.list:set_position(0, 0)

  self.list:set_size(
    size.x,
    self.add:get_height() * 3 - (style.padding.y * 2)
  )

  self.add:set_position(0, self.list:get_bottom() + style.padding.y)

  self.remove:set_position(
    self.add:get_right() + (style.padding.x / 2),
    self.list:get_bottom() + style.padding.y
  )

  size.y = self.add:get_bottom() + self.add.border.width * 2
end


return ItemsList
