---
-- @package   eg4-crank-ui
-- @file      network-connections.lua
-- @brief     Handles the network connections settings.
--
-- @copyright Copyright 2025 Hanover Displays Limited.
-- @license   This program is the confidential and proprietary product of
--            Hanover Displays Limited. Any unauthorised use, reproduction or
--            transfer of this program is strictly prohibited. (Subject to
--            limited distribution and restricted disclosure only.) All
--            rights reserved.
--
--

--- Local cache for settings
local settings

---
--- @brief  Processes the currently avaialble G4 protocol list; populating the linked protocol screen.
--- @param  gre#context mapargs
---
local function ProcessAvailableG4NetworkProtocols(mapargs)
  local protocols = sbsettings.read_available_g4_protocols()
  local group = "network_connection_linked_protocol_layer.group"
  local control = group..".items"

  -- Adjust table to number of rows available
  gre.set_table_attrs(control, {height = #protocols * 81})
  gre.set_table_attrs(control, {rows = #protocols})

  gre.set_control_attrs(group..".horizontal_divider", {y = #protocols * 81- 1})

  local data = {}
  for row,value in ipairs(protocols) do
    data[string.format(control..".text.%d.1", row)] = value
    data[string.format(control..".checked.%d.1", row)] = 0
    data[string.format(control..".fade.%d.1", row)] = 0
  end

  gre.set_data(data)
end

---
--- @brief  Adds a network connection to the list table.
--- @param  gre#context mapargs
---
function CBInitNetworkConnectionsList(mapargs)
  settings = {}

  ProcessAvailableG4NetworkProtocols(mapargs)

  mapargs.context_layer = "network_connections_layer"
  local group = mapargs.context_layer..".group"
  local control = group..".items"

  local connections = sbsettings.read_g4_network_connections()

  -- Add the new item to the menu list.
  local data = {}
  local index = 0
  for _, port_id in pairs(connections) do
    index = index + 1
    data[string.format(control..".port_id.%d.1", index)] = port_id
    data[string.format(control..".text.%d.1", index)] = port_id
    local protocol = sbsettings.get_network_port_connection_linked_protocol(port_id)
    data[string.format(control..".value.%d.1", index)] = protocol
    data[string.format(control..".fade.%d.1", index)] = 0
  end
  data[group .. ".add_new_connection.grd_y"] = index * 81
  gre.set_data(data)

  gre.set_table_attrs(control, { height = index * 81, rows = index })

  SBCInitialiseScrollbar(mapargs)
end

---
--- @brief  Creates a port id string from the given port id.
--- @param  port_id
--- @return port id string
local function MakePortID(port_id)
  local transport = get_network_connection_transport(port_id)
  local port_no = get_network_connection_port_no(port_id)
  local mode = get_network_connection_mode(port_id)
  local domain = get_network_connection_domain(port_id)
  return string.format("%s://%s:%s", transport == 0 and "udp" or "tcp", mode == 0 and "@" or domain, port_no)
end

---
--- @brief  Writes the network connection settings to the given port id.
--- @param  port_id
local function WriteNetworkConnection(port_id)
  local port_id = settings.port_id or port_id or ""
  local url = MakePortID(port_id)
print(": ", port_id, url)
  local updated
  if port_id ~= "" and port_id ~= url then
    sbsettings.set_network_port_connection_linked_protocol("-", port_id)
    updated = true
  end

  local domain = url:match(".-://(.-):") or ""
  if domain ~= "" then 
    local linked_protocol = get_network_connection_linked_protocol(port_id)
    sbsettings.set_network_port_connection_linked_protocol(linked_protocol, url)
    settings.port_id = url
    updated = true
  end

  if updated then
    SendEvent("settings_updated")
  end
end

---
--- @brief  Gets the linked protocol for the given port id.
--- @param  port_id
--- @return linked protocol
function get_network_connection_linked_protocol(port_id)
  if not settings.protocol then
    settings.protocol = sbsettings.get_network_port_connection_linked_protocol(port_id) or "-"
  end
  return settings.protocol
end

---
--- @brief  Sets the linked protocol for the given port id.
--- @param  value linked protocol
--- @param  port_id
function set_network_connection_linked_protocol(value, port_id)
  settings.protocol = value
  WriteNetworkConnection(port_id)
end

---
--- @brief  Gets the transport type for the given port id.
--- @param  port_id
--- @return transport type
function get_network_connection_transport(port_id)
  if not settings.transport then
    settings.transport = port_id:starts_with("tcp://") and 1 or 0
  end
  return settings.transport
end

---
--- @brief  Sets the transport type for the given port id.
--- @param  value transport type
--- @param  port_id
function set_network_connection_transport(value, port_id)
  settings.transport = value
  WriteNetworkConnection(port_id)
end

---
--- @brief  Gets the port number for the given port id.
--- @param  port_id
--- @return port number
function get_network_connection_port_no(port_id)
  if not settings.port_no then
    local port_no = port_id:match(".-://.-:(%d+)")
    settings.port_no = port_no or "0"
  end
  return settings.port_no
end

---
--- @brief  Sets the port number for the given port id.
--- @param  value port number
--- @param  port_id
function set_network_connection_port_no(value, port_id)
  settings.port_no = value
  WriteNetworkConnection(port_id)
end

---
--- @brief  Gets the connection mode for the given port id.
--- @param  port_id
--- @return 0 server, 1 client
function get_network_connection_mode(port_id)
  if not settings.mode then
    if port_id == "" then
      settings.mode = 0
    else
      local domain = port_id:match(".-://(.-):") or ""
      settings.mode = domain == "@" and 0 or 1
    end
  end
  return settings.mode
end

---
--- @brief  Sets the connection mode for the given port id.
--- @param  value - 0 server, 1 client
--- @param  port_id
function set_network_connection_mode(value, port_id)
  settings.mode = value
  WriteNetworkConnection(port_id)
end

---
--- @brief  Gets the domain for the given port id.
--- @param  port_id
--- @return domain or ip address
function get_network_connection_domain(port_id)
  if not settings.domain then
    local domain = port_id:match(".-://(.-):") or ""
    if domain == "@" then domain = "" end
    settings.domain = domain or ""
  end
  return settings.domain
end

---
--- @brief  Sets the domain for the given port id.
--- @param  value domain or ip address
--- @param  port_id
function set_network_connection_domain(value, port_id)
  settings.domain = value
  WriteNetworkConnection(port_id)
end

---
--- @brief  Callback to handle the setting of the network connection domain or ip address.
--- @param  value domain or ip address
--- @param  port_id
function CBSubmitNetworkConnectionDomain(mapargs)
  set_network_connection_domain(mapargs.value, gre.get_value(mapargs.context_screen..".port_id"))
  TransitionBackScreen(mapargs)
end

---
--- @brief  Callback to set the port number for the given port id.
--- @param  value port number
--- @param  port_id
function CBWriteNetworkConnectionPortNo(mapargs)
  set_network_connection_port_no(mapargs.value, gre.get_value(mapargs.context_screen..".port_id"))
  TransitionBackScreen(mapargs)
end
