--[[
  @package    eg4-crank-ui-2
  @file       checkbox-list.lua
  @brief      Supports the operation of checkbox list screen
]]


local SCREEN = "general_checkbox_select"

local info

---
--- @brief  Initialise the checkbox list screen
--- @param  mapargs.heading       The heading to display on the screen
--- @param  mapargs.event         The event to send when the selection changes
--- @param  mapargs.callback      The callback to run when the selection changes
--- @param  mapargs.parameter     The parameter to get/set when the selection changes [optional]
--- @param  mapargs.guard         The guard function to determine whether the selection can be changed [optional]
--- @param  mapargs.more          The function to run when the more button is pressed [optional]
--- @param  mapargs.port_id       The port id to set the parameter on
--- @param  mapargs.as_value      The item is a value rather than an index
--- @param  mapargs.value         The initial value [optional]
--- @param  mapargs.on_exit       The function to run when the screen is exited [optional]
--- @param  mapargs.list          The list of items to display
--- @param  mapargs.list.text     The text to display for the item
--- @param  mapargs.list.value    The value to set for the item
--- @param  mapargs.list.data     The data to pass to the callback when the item is selected
--- @param  mapargs.list.checked  1 if the item is checked

function start_checkbox_list(mapargs)
  local fn = "set_"..(mapargs.parameter or "no_action")
  info = {
    more       = type(mapargs.more) == "function" and mapargs.more or _G[mapargs.more],
    guard      = type(mapargs.guard) == "function" and mapargs.guard or _G[mapargs.guard],
    event      = mapargs.event,
    callback   = type(mapargs.callback) == "function" and mapargs.callback or _G[mapargs.callback],
    set        = _G[fn] or sbsettings[fn],
    port_id    = mapargs.port_id,
    as_value   = mapargs.as_value,
    on_exit    = type(mapargs.on_exit) == "function" and mapargs.on_exit or _G[mapargs.on_exit],
  }

  local data = {}
  local control = get_list_control(SCREEN)
  for row, item in ipairs(mapargs.list) do
    data[control..".text."         ..row..".1"] = item.text
    data[control..".value."        ..row..".1"] = item.value or ""
    data[control..".data."         ..row..".1"] = item.data or ""
    data[control..".checked."      ..row..".1"] = item.checked == 1 and 255 or 0
    data[control..".more."         ..row..".1"] = info.more and 255 or 0
    data[control..".alpha_pressed."..row..".1"] = 0
    if item.checked == 1 and not info.selected then
      info.selected = row
    end
  end

  data[SCREEN..".heading"] = mapargs.heading
  data[SCREEN..".accept"] = mapargs.accept or ""

  gre.set_data(data)

  local height = #mapargs.list * gre.get_table_cell_attrs(control, 1, 1, "height").height
  gre.set_table_attrs(control, { rows = #mapargs.list, height = height })

  screen_transition(SCREEN)
end

---
--- @brief  Update the screen check for navigation to first selected item
--- @param  mapargs  The map arguments from the callback
function cb_update_checkbox(mapargs)
  cb_update_menu(mapargs)
  -- Navigate to the first selected item's page
  if info.selected then
    mapargs.dir = math.floor((info.selected - 1) / 5)
    cb_page_navigate(mapargs)
  end
end

---
--- @brief  Update the option with the selected radio item
function cb_checkbox_select(mapargs)
  -- Get port id from parameter, group, or screen
  mapargs.port_id = info.port_id

  if info.more and mapargs.context_event_data.x > gre.get_value(mapargs.context_control..".grd_width") / 2 then
    info.more(mapargs)
    return
  end

  local cell = mapargs.context_control..".checked."..mapargs.context_row..".1"

  mapargs.value = 0
  if not info.guard or info.guard(mapargs) then
    mapargs.value = 255 - (gre.get_value(cell) or 0)
  end
  gre.set_value(cell, mapargs.value)

  if info.set then
    if tonumber(info.as_value) == 1 then
      local text = gre.get_value(mapargs.context_control..".text."..mapargs.context_row..".1")
      info.set(mapargs.value == 255 and 1 or 0, text, mapargs.port_id)
    else
      info.set(mapargs.value == 255 and 1 or 0, mapargs.context_row, mapargs.port_id)
    end
  end
  -- If specified, run callback
  if info.callback then
    mapargs.set = info.set
    info.callback(mapargs)
  end

  if info.event then
    send_event(info.event)
  end
end

---
--- @brief  Run the on_exit function when the screen is exited
function cb_checkbox_on_exit()
  if info.on_exit then
    info.on_exit()
  end
end