---
-- @package   eg4-crank-ui
-- @file      write-string-list.lua
-- @brief     Functionality for writing the strings from the model to a file.
--            The current language facility does not properly determine all 
--            the strings that require translation from the model. Ay start-up, 
--            this module will scan the model and pickup all the strings and 
--            write them to a file. 
--            Note: This only works when the model is run on the computer. This 
--            is intention behaviour.
--
-- @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  Check if value represents a image
--- @param  value - item to check
---
local function CheckValueIsImage(value)
  if string.sub(tostring(value), 1, 7) == "images/" then
    if string.sub(tostring(value), -4) == ".png" or
       string.sub(tostring(value), -4) == ".jpg" or
       string.sub(tostring(value), -4) == ".gif" then
          return true
    end
  end
  return false
end

---
--- @brief  Check if value represents a function callback
--- @param  value - item to check
---
local function CheckValueIsFunction(value)
  if type(value) == "function" or _G[value] ~= nil then
    return true
  elseif tostring(value):starts_with("CB") or tostring(value):starts_with("cb_") then
    return true
  end
  return false
end

--- 
--- @brief  Check if value represents a reserved string
--- @param  value - item to check
--- @return true if reserved string
local function CheckReservedString(value)
  local reserved_strings = {
    "%d%%",
    "%d%% - %d%%",
    "%1.0f",
    "%.1f",
    "%d%%",
    "UDP",
    "TCP",
    "HTC",
    "IBIS1",
    "STFT1",
    "OBC1"
  }
  for i=1,#reserved_strings do
    if value == reserved_strings[i] then
      return true
    end
  end
  return false
end

---
--- @brief  Check if value represents a non numerical string
--- @param  value - item to check
---
local function CheckValueIsString(value)
  if CheckValueIsFunction(value) then
    return false
  elseif CheckValueIsImage(value) then
    return false
  elseif CheckReservedString(value) then
    return false
  end
  if type(value) == "string" then
    if gredom.get_object(value) == nil then
      if string.match(value, '[A-Za-z]+') ~= nil then
        if string.match(value, '[_]+') == nil then
          return true
        end
      end
    end
  end
  return false
end

---
--- @brief  Checks for valid string and if valid creates a data item to be written to the csv file. 
--- @param  var - variable to parse
--- @param  value - value of variable 
---
local function populateStringItem(var, value)
  if (var:sub(1, 31) == "banner_icon_menu_layer.controls") and (var:sub(-19) == "_control.short_name") then return nil end
  if not CheckValueIsString(value) then return nil end
  local text_name = var:sub(var:match(".*%.()") or 1)
  var = var:sub(1, var:match(".*%.()") - 2)
  local data = {}
  local base = var:sub(1, (var:match("%.()") or 1) - 2)
  data.text_width = gre.get_value(var.."."..text_name.."_width") or gre.get_value(var..".width") or gre.get_value(base.."."..text_name.."_width") or gre.get_value(var..".grd_width")  or gre.get_value(text_name.."_width") or -1
  data.font_size = gre.get_value(var..".font_size") or 24
  data.font_style = 'Noto Sans SC Regular'
  data.text = value
  return data
end

---
--- @brief  Scans var item for individual string or list and adds item(s) to list
---         string list with all items.
--- @param  string_list - list to populate
--- @param  var - variable to parse
---
local function ParseStringToFile(string_list, var)
  local status = false
  local row = 1
  repeat
    local value
    local col = 1
    local item = string.format("%s.%u.%u", tostring(var), row, col)
    value = gre.get_value(item)
    if value ~= nil then
      status = true
      repeat
        string_list[item] = populateStringItem(var, value)
        col = col + 1
        item = string.format("%s.%u.%u", tostring(var), row, col)
        value = gre.get_value(item)
      until value == nil
      value = ""
    end
    row = row + 1
  until value == nil
  
  if status == false then
    local value = gre.get_value(var)
    string_list[var] = populateStringItem(var, value)
  end
end

---
--- @brief  Search the object for strings that require translation.
--- @param  string_list - list to populate
--- @param  dom_object - parent object 
---
local function SearchVariablesForStrings(string_list, dom_object)
  if(dom_object == nil) then
    return
  end

  local vars = dom_object:get_variables()
  if vars ~= nil and #vars ~= 0 then
    for i=1,#vars do
      ParseStringToFile(string_list, tostring(vars[i]))
    end
  end
end

---
--- @brief  Nested search of all objects for translations
--- @param  string_list - list to populate
--- @param  dom_object - parent object 
---
local function SearchObjectChildrenForStrings(string_list,  dom_object)
  SearchVariablesForStrings(string_list, dom_object)  
  local objects = dom_object:get_children()
  for i = #objects, 1, -1 do
    SearchObjectChildrenForStrings(string_list, objects[i])
  end
end

---
--- @brief  Callback to collect all the strings from the model and write them to a file.
--- @param  gre#context mapargs
---
function CBCollectStringsForTranslation(mapargs)
  -- Note: this open will intentionally fail on the target.
  file = io.open ("translations/string-list.csv", "w")
  if file == nil then return end

  local dom_object = gredom.get_application()
  local objects = dom_object:get_children()
  local string_list = {}
  for i = #objects, 1, -1 do
    SearchObjectChildrenForStrings(string_list, objects[i])
  end  

  -- Create a table of keys and sort
  local keys = {}
  for k, v in pairs(string_list) do
    table.insert(keys, k)
  end
  table.sort(keys)

  -- Write to file
  for _,k in pairs(keys) do
    local v = string_list[k]
    if v.text:find('[,"]') then
      v.text = '"'..v.text:gsub('"', '""')..'"'
    end    
    file:write(string.format('%s,%d,%d,%s,%s\n', k, v.text_width, v.font_size, v.font_style, v.text))
  end
  file:close()
end

-- EOF --
