---
--- @package   eg4-crank-ui
--- @file      battery-status.lua
--- @brief     Functionality related to the checkbox controls.
---
--- @copyright Copyright 2019 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.                                              
---

---
--- @brief  Updates the state of the checkbox
--- @param  control - checkbox control
--- @param  value - state to set. (nil, 0 or false is unchecked; everything else checked)
--- @param  row - row for table based checkbox lists.
--- @return checked status 0 or 1  
---
function SetCheckboxValue(control, value, row)

  local item = control .. ".checked" 
  local fade = control .. ".fade"

  if row ~= nil then
    item = item .. "." .. row .. ".1"
    fade = fade .. "." .. row .. ".1"
  end
    
  if value == nil or value == 0 or value == false then
    gre.set_value(item, 0, fade, 0)
    value = 0
  else
    gre.set_value(item, 255, fade, 0)
    value = 1
  end
  return value
end

---
--- @brief  Build a string containing the checkbox value items.
--- @param  control - control that has the value text
--- @param  settings - table of setting values.
--- @return text containg string or nil if not found
---
function GetCheckboxTextValue(control, settings)
  local value
  local sep = ""
  for index,enabled in pairs(settings) do
    if tonumber(enabled) ~= 0 then
      local text = gre.get_value(control..".text."..index..".1")
      if text and text ~= "" then
        value = (value or "")..sep..text
        sep = ","
      end
    end
  end
  return value
end

----
--- @brief  Populate checkbox items from a CSV string of checkbox texts
--- @param  gre#context mapargs
---
local function PopulateFromCSV(control, items)
  -- Split the setting string
  local items = items:split(",")
  local index = 0
  while true do
    index = index + 1
    local text = gre.get_value(control..".text."..index..".1")
    if text == nil then break end
    local enabled = 0
    for _,v in ipairs(items) do
      if v == text then
        enabled = 1                
        break
      end
    end
    SetCheckboxValue(control, enabled, index)
  end
end

----
--- @brief  Populate checkbox items for the current context setting.
--- @param  gre#context mapargs
---
function CBUpdateCheckboxes(mapargs)
  local screen = mapargs.context_screen or mapargs.active_context
  local layers = screen and GetChildObjectList(screen)
  if layers == nil then return nil end
  -- find the layer with the checkbox item
  for i = #layers,1,-1 do
    local layer = tostring(layers[i])
    layer = layer:split(".")
    layer = layer[#layer]
    local group = layer..".group"
    local control = group..".items"
    if gre.get_value(control..".checked.1.1") ~= nil then
      -- Located checkbox layer, populate with settings
      local items = gre.get_value(screen..".value")
      if items then
        PopulateFromCSV(control, items)
      else
        local fn = "get_"..layer:sub(1,-7)
        fn = _G[fn] or sbsettings[fn] 
        if fn then
          local port_id = gre.get_value(group..".port_id") or gre.get_value(screen..".port_id")
          -- Get active items from screen or 
          local items = fn(port_id)
          if type(items) == "table" then
            for index, enabled in ipairs(items) do
              SetCheckboxValue(control, enabled, index)
            end
          elseif type(items) == "string" then
            PopulateFromCSV(control, items)
          end
        end
      end
      return
    end
  end
end

---
--- @brief  Toggles the checkbox and calls the callback function.
--- @param  gre#context mapargs
function CBToggleCheckbox(mapargs)
  if not ScrollActive() then
    local control
    local fn = _G[mapargs.more or gre.get_value(mapargs.context_control..".more")]
    if fn and mapargs.context_event_data.x > gre.get_value(mapargs.context_control..".grd_width") / 2 then
      fn(mapargs)
    else
      local item = mapargs.context_control .. ".checked" 
      if mapargs.context_row ~= nil then
        item = item .. "." .. mapargs.context_row .. ".1"
      end

      local value = 0
      if not mapargs.guard or _G[mapargs.guard](mapargs) then
        value = 255 - (gre.get_value(item) or 0)
      end

      mapargs.value = SetCheckboxValue(mapargs.context_control, value, mapargs.context_row)
  
      -- Get port id from parameter, group, or screen
      mapargs.port_id = mapargs.port_id or gre.get_value(mapargs.context_group..".port_id") or gre.get_value(mapargs.context_screen..".port_id")

      -- Check if a set function exists for this component.
      local fn = "set_"..mapargs.context_layer:sub(1,-7)
      local fn = _G[fn] or sbsettings[fn]
      if fn then
        if tonumber(mapargs.as_value) == 1 then
          local text = gre.get_value(mapargs.context_control..".text."..mapargs.context_row..".1")
          fn(mapargs.value, text, mapargs.port_id)
        else
          fn(mapargs.value, mapargs.context_row, mapargs.port_id)
        end
      end
  
      -- If specified, run callback
      local callback = _G[mapargs.callback] or _G[gre.get_value(mapargs.context_control..".callback")]
      if type(callback) == "function" then
        callback(mapargs)
      end
  
      -- If specified, send event to backend
      local event = mapargs.event or gre.get_value(mapargs.context_control..".event")
      if event then
        SendEvent(event)
      end
    end
  end
end

---
--- @brief  Test callback for checkbox. Just prints the new value to console.
--- @param  value - current state (1 or 0)
--- @param  row - nil or row of table based checkbox. 
---
function CBCheckboxTest(mapargs)
  if mapargs.context_row == nil then
    print(mapargs.value)
  else
    print(mapargs.context_row .. " - " .. mapargs.value)
  end
end

-- EOF --
