--[[
  @package    eg4-crank-ui-2
  @file       htc-terminal.lua
  @brief      Supports the HTC features and notifications
]]

local LAYER = "htc_terminal_layer"
local SIMULATED_WIDTH = 256


---
--- @brief  Updates the audio announcement (htc) icon.
function show_audio_announcement()
  return (sbsettings.get_htc_hot_key_select_enable() == 1) and (sbsettings.get_htc_hot_key_icon() == 1)
end

---
--- @brief  Updates the HTC hot key icon.
function show_htc_hot_key()
  return (sbsettings.get_htc_hot_key_select_enable() == 1) and (sbsettings.get_htc_hot_key_icon() == 0)
end

---
---
--- @brief  Updates the HTC Terminal icon/menu.
function show_htc_terminal(screen)
  -- Either get the specific control_id for the screen or the first OBC control_id
  local control_id = gre.get_value(screen..".control_id") or cb_fetch_first_obc_control_id()
  if not check_control_id_is_obc(control_id) then
    return
  end
  if check_virtual_obc(control_id) and sbsettings.get_enable_virtual_htc_terminal() == 0 then
    return
  end
  gre.set_value(screen..".htc_control_id", control_id)
  return true
end

---
--- @brief  Updates the HTC Driver menu.
function show_htc_driver_menu(screen)
  return (sbsettings.get_driver_htc_terminal_permission() == 1) and show_htc_terminal(screen)
end

---
--- @brief  Start the HTC hot key select
--- @param  mapargs  The mapargs
function cb_start_htc_hot_key_select(mapargs)
  local list = get_htc_hot_key_select_list()
  if #list == 0 then
    cb_numeric_entry_start(mapargs)
  else
    screen_transition("general_item_select")
  end
end

---
--- @brief  Initialise the screen with the HTC hot key select list
--- @param gre#context mapargs
function cb_initialise_htc_hot_key_select_list(mapargs)
  local list = get_htc_hot_key_select_list()
  local control = get_list_control(mapargs.context_screen)
  local data = {}
  local rows = 0
  for _,value in ipairs(list) do
    rows = rows + 1
    data[control..".text."..rows..".1"] = value
    data[control..".alpha_pressed."..rows..".1"] = 0
    data[control..".more."..rows..".1"] = 0
  end
  data[control..".grd_height"] = rows * gre.get_table_cell_attrs(control, 1, 1, "height").height
  gre.set_data(data)
  gre.set_table_attrs(control, { rows = rows })
  cb_update_menu(mapargs)
end

---
--- @brief  Process the HTC hot key selected item
--- @param gre#context mapargs
function cb_htc_hot_key_item_selected(mapargs)
  local text = gre.get_value(mapargs.context_control..".text."..mapargs.context_row..".1")
  local value = string.match(text, "%w+")
  if value ~= nil then
    for i = 1, #value do
      send_event("terminal_key_press", string.sub(value, i, i))
    end
  end
  screen_transition_idle()
end

---
--- @brief  Send HTC hot key to backend
--- @param  key  The key to send
function cb_htc_process_hot_key(key)
  send_event("terminal_key_press", key)
end

---
--- @brief  HTC Hot key processing complete
function cb_htc_hot_key_complete()
  cb_htc_process_hot_key("\n")
  screen_transition_idle()
  return true
end

---
--- @brief  Send the terminal key press to the backend
--- @param gre#context mapargs
function cb_htc_terminal_key_press(mapargs)
  send_event("terminal_key_press", mapargs.context_control:object_name())
end

---
--- @brief  Process the clear terminal display event
function cb_clear_display_terminal()
  delete_all_child_objects(LAYER..".display")
end

---
--- @brief  Send enter terminal mode event
function cb_enter_terminal_mode(mapargs)
  local control_id = gre.get_value(mapargs.context_screen..".control_id")
  local locked_mode = gre.get_value(mapargs.context_screen..".locked_mode") or "1"
  local endpoint = get_end_point_text_for_control_id(control_id)
  send_event("enter_terminal_mode", endpoint.." "..locked_mode)
end

---
--- @brief  Send exit terminal mode event
---
function cb_exit_terminal_mode(mapargs)
  local control_id = gre.get_value(mapargs.context_screen..".control_id")
  local endpoint = get_end_point_text_for_control_id(control_id)
  send_event("exit_terminal_mode", endpoint)
end

---
--- @brief  Process the display fields in the terminal text event
---
--- @param gre#context mapargs
function cb_process_htc_terminal_text(mapargs)
  local info = loadstring(mapargs.context_event_data.text)()
  local group = LAYER..".display"

  if info.clear_display == 1 then
    delete_all_child_objects(group)
  end

  local template = LAYER..".template.field"
  local scaling = (gre.get_value(template) or 512) / SIMULATED_WIDTH
  local data = {}
  for _,field in ipairs(info.fields) do

    local control = field.justified .. "_"..field.line_no.."_"..field.offset
    if gre.get_value(control..".x") == nil then
      gre.clone_object(template, control, group, { hidden = 0 })
    end
    local control = group.."."..control

    data[control..".text"] = field.text
    if field.justified == "right" then
      data[control..".halign"] = 3
    elseif field.justified == "center" then
      data[control..".halign"] = 2
    else
      data[control..".halign"] = 1
    end
    if field.line_no == 2 then
      data[control..".valign"] = 3
    elseif field.line_no == 1 then
      data[control..".valign"] = 2
    else
      data[control..".valign"] = 1
    end
    data[control..".text"] = field.text
    data[control..".x"] = math.floor((field.offset or 0) * scaling + 0.5)
  end
  gre.set_data(data)
end

---
--- @brief  Set the virtual htc terminal port
--- @param  value  The port number
--- @return true if the port number is valid
function cb_virtual_htc_terminal_port_set(value)
  if value == "" or not cb_port_number_validate(value) then return end
  sbsettings.set_virtual_htc_terminal_port(tonumber(value))
  cb_back_screen()
  return true
end

---
--- @brief  Validate the port number
--- @param  value  The port number
--- @return true if the port number is valid
function cb_port_number_validate(value)
  if value == "" then return true end
  value = tonumber(value)
  return value and value > 0 and value < 65536
end
