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


local SCREEN = "general_radio_select"

local info

---
--- @brief  Initialise the radio select screen from the info
--- @param  mapargs  The mapargs from the event
function cb_init_radio_select(mapargs)

  if info.set == nil then
    local fn = "set_"..info.parameter
    info.set = _G[fn] or sbsettings[fn]
  end

  if info.value == nil then
    local fn = "get_"..info.parameter
    fn = _G[fn] or sbsettings[fn]
    info.value = fn(info.port_id)
  end

  local data = {}
  data[mapargs.context_screen..".heading"] = info.heading

  local control = get_list_control(mapargs.context_screen)

  local count = 0
  info.mapping = {}
  for index, text in ipairs(info.list) do
    -- Only add non-empty items
    if text ~= "" then
      count = count + 1
      data[control..".text."..count..".1"] = text
      local radio = (info.as_value == 1) and (tostring(text) == tostring(info.value)) or (index - 1 == info.value)
      if radio then
        info.selected = count
      end
      data[control..".radio."..count..".1"] = radio and 255 or 0
      data[control..".alpha_pressed."..count..".1"] = 0
      data[control..".alpha_more."..count..".1"] = info.radio_more and 255 or 0
      data[control..".value."..count..".1"] = info.radio_value and _G[info.radio_value](index - 1) or ""
      info.mapping[count] = index
    end
  end

  data[control..".grd_height"] = count * gre.get_table_cell_attrs(control, 1, 1, "height").height
  gre.set_table_attrs(control, { rows = count })

  gre.set_data(data)

  cb_update_menu(mapargs)

  -- Navigate to the selected item's page
  if info.selected then
    mapargs.dir = math.floor((info.selected - 1) / 5)
    cb_page_navigate(mapargs)
  end
end

---
--- @brief  Initialise the radio select screen for the given option
--- @param  mapargs  The mapargs from the event
--- @param  list     The list of items to display (optional)
function cb_start_radio_select(mapargs, list)
  info = {
    event = gre.get_value(mapargs.context_control..".event"),
    callback = gre.get_value(mapargs.context_control..".callback"),
    parameter = mapargs.parameter or mapargs.context_control:object_name(),
    heading = gre.get_value(mapargs.context_control..".heading") or gre.get_value(mapargs.context_control..".text"),
    as_value = gre.get_value(mapargs.context_control..".as_value"),
    allow_selected = gre.get_value(mapargs.context_control..".allow_selected") or 0,
    port_id = gre.get_value(mapargs.context_screen..".port_id"),
    radio_value = gre.get_value(mapargs.context_control..".radio_value"),
    radio_more = gre.get_value(mapargs.context_control..".radio_more"),
  }

  local fn = gre.get_value(mapargs.context_control..".list_fn")
  fn = _G[fn] or sbsettings[fn]
  if fn then list = fn() end

  if list then
    if type(list) == "userdata" then
      info.list = {}
      for i = 1, #list do
        table.insert(info.list, list[i])
      end
    else
      info.list = list
    end
  else
    info.list = {}
    local index = 0
    while true do
      index = index + 1
      local item = gre.get_value(mapargs.context_control..".radio."..index..".1")
      if item == nil then break end
      table.insert(info.list, item)
    end
  end

  screen_transition(mapargs.screen or SCREEN)
end

---
--- @brief  Start radio selection from the given init
--- @param  init  The initialisation data
function start_radio_select(init)
  info = init
  screen_transition(SCREEN)
end

---
--- @brief  Update the option with the selected radio item
function cb_radio_select(mapargs)
  local control = mapargs.context_control

  -- Call more function if touch is on the right side of the control.
  local fn = _G[info.radio_more]
  if fn and mapargs.context_event_data.x > gre.get_value(control..".grd_width") / 2 then
    fn(mapargs)
  end

  if info.allow_selected == 0 and info.selected == mapargs.context_row then return end
  local data = {}
  data[control..".radio."..(info.selected or 0)..".1"] = 0
  data[control..".radio."..mapargs.context_row..".1"] = 255
  gre.set_data(data)

  info.selected = mapargs.context_row
  if info.as_value == 1 then
    local value = gre.get_value(mapargs.context_control..".text."..mapargs.context_row..".1")
    info.set(tonumber(value) or value, info.port_id)
  else
    info.set(info.mapping[mapargs.context_row] - 1, info.port_id)
  end

  if info.callback then
    _G[info.callback](mapargs)
  end

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