--[[
  @package    eg4-crank-ui-2
  @file       information-list.lua
  @brief      Handles the information browser list
]]

local BROWSE_LAYER = "information_browse_layer"
local BROWSE_LIST_CONTROL = BROWSE_LAYER..".list"
local NAVIGATION_GROUP = BROWSE_LAYER..".navigate"

local info = {}

---
--- @brief  Fetches the last filter value.
--- @return route code or ""
local function get_last_information_filter_value()
  return info.last_filter_value or ""
end

---
--- @brief  Get the height of the recent list layer
--- @return The layer height
local function get_table_height()
  return gre.get_value(BROWSE_LIST_CONTROL..".grd_height")
end
---
--- @brief  Get the number of items per page
--- @return The number of items per page
local function get_items_per_page()
  local control_height = gre.get_table_cell_attrs(BROWSE_LIST_CONTROL, 1, 1, "height").height
  return math.floor(get_table_height() / control_height + 0.5)
end

---
--- @brief  Set the navigation controls depending on the current index
local function set_navigation_controls()
  local scroll_marker_top = 0
  if info.pages > 1 then
    local height = gre.get_value(NAVIGATION_GROUP..".sep.grd_height")
    local sep = gre.get_value(NAVIGATION_GROUP..".sep.height")
    scroll_marker_top = math.floor((height - sep) * info.page / (info.pages - 1) + 0.5)
  end

  local data = {}
  data[NAVIGATION_GROUP..".sep.y"] = scroll_marker_top
  data[NAVIGATION_GROUP..".up.grd_active"] = info.page > 0
  data[NAVIGATION_GROUP..".up.alpha_disabled"] = info.page > 0 and 255 or 83
  data[NAVIGATION_GROUP..".down.grd_active"] = info.page < info.pages - 1
  data[NAVIGATION_GROUP..".down.alpha_disabled"] = (info.page < info.pages - 1) and 255 or 83
  data[NAVIGATION_GROUP..".paging.grd_hidden"] = info.pages < 2
  data[NAVIGATION_GROUP..".paging.rich_text"] = make_page_text(info.page + 1, info.pages)
  gre.set_data(data)
end

---
--- @brief  Update the information list table.
local color_pressed
local color_normal
local color_select
local function update_information_list()
  set_navigation_controls()
  color_pressed = gre.get_value("color_list_pressed_text_option")
  color_normal = gre.get_value("color_list_text_option")
  color_select = gre.get_value("color_list_text_title")
  animate_variable(BROWSE_LIST_CONTROL..".scrolling_bind", info.page * info.items_per_page)
end

function cb_update_information_list(mapargs)
  local data = {}
  local rows = info.items_per_page
  local index = gre.get_value(mapargs.context_control..".scrolling_bind")
  for i=1,info.items_per_page do
    local text = get_info_message_list_item(index + i)
    if text == nil then rows = i - 1 break end
    data[mapargs.context_control..".info_id."..i..".1"] = text:match("^(%w+) ")
    data[mapargs.context_control..".text."..i..".1"] = highlight_filtered_text(text, info.last_filter_value, color_normal, color_select)
    data[mapargs.context_control..".released."..i..".1"] = data[mapargs.context_control..".text."..i..".1"]
    data[mapargs.context_control..".pressed."..i..".1"] = highlight_filtered_text(text, info.last_filter_value, color_pressed, color_pressed)
  end
  gre.set_data(data)
  gre.set_table_attrs(mapargs.context_control, { rows = rows, hidden = (rows == 0) })
end

---
--- @brief  Initialises the list to the current data value.
--- @param  filter  The filter to apply
function cb_initialise_information_list(filter)
  if filter == "" or type(filter) ~= "string" then filter = nil end
  if get_last_information_filter_value() == filter then return end
  filter = filter or ""

  update_info_message_list(filter)

  -- Center on previously highlighted item if present
  info.size = get_info_message_list_size()
  info.items_per_page = get_items_per_page()
  info.pages = math.ceil(info.size / info.items_per_page)
  info.page = 0
  info.last_filter_value = filter

  gre.set_value(BROWSE_LIST_CONTROL..".scrolling_bind", 0)
  update_information_list()
  cb_update_information_list({ context_control = BROWSE_LIST_CONTROL })
end

---
--- @brief  Callback to perform the navigation repeat
--- @param  dir  The direction to navigate (-1 for up, 1 for down)
--- @return true if the navigation was rejected
function cb_information_list_navigate(mapargs)
  info.page = info.page + mapargs.dir
  if info.page < 0 then
    info.page = 0
    return true
  end
  if info.page >= info.pages then
    info.page = info.pages - 1
    return true
  end
  update_information_list()
end
