---
--- @package   eg4-crank-ui
--- @file      audio-settings.lua
--- @brief     Functionality to support the editing of audio settings. 
---
--- @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  Populates the audio settings list.
--- @param gre#context mapargs
function CBInitAudioSettingList(mapargs)
  local layer = "audio_settings_layer"
  local group = layer..".group"
  local control = group..".items"
  for _,audio_id in pairs(sbsettings.read_audio_list()) do
    -- Determine if item is already present. 
    local index = 0
    local port_id
    repeat
      index = index + 1
      port_id = gre.get_value(string.format(control..".port_id.%d.1", index))
    until port_id == nil or port_id == "" or audio_id == port_id 

    if port_id ~= audio_id then
      -- Add the new item to the menu list.
      port_id = audio_id
      local text = string.format(gre.get_value(control..".format"), port_id)
      gre.set_value(string.format(control..".text.%d.1", index), text, 
                    string.format(control..".port_id.%d.1", index), port_id)
      gre.set_table_attrs(control, { height = index * 81, rows = index })
    end

    -- Populate the value with the assigned audio uses
    local text = GetControlValueText(control, "audio_use", port_id)
    gre.set_value(string.format(control..".value.%d.1", index), text)
  end
end

---
--- @brief  Update option for audio settings depending on whether audio is available.
--- @param  gre#context mapargs
function CBUpdateAudioSettings(mapargs)
  if next(sbsettings.read_audio_list()) then
    gre.set_value("system_configuration_layer.menu_items.audio_settings.grd_hidden", 0)
  end
end

---
--- @brief  Initialises the audio setting screen. Setting the port id 
---         to indicate what is currently selected.
--- @param  gre#context mapargs
function CBInitAudioSettingScreen(mapargs)
  local heading = gre.get_value(string.format(mapargs.context_control..".text.%d.1", mapargs.context_row))
  gre.set_value("mo_audio_setting.banner_heading", heading)
  local port_id = gre.get_value(string.format(mapargs.context_control..".port_id.%d.1", mapargs.context_row))
  gre.set_value("audio_setting_layer.menu_items.port_id", port_id)
  ScreenTransition("mo_audio_setting")
end

---
--- @brief  Start the audio use settings screem
--          setting display.
--- @param gre#context mapargs
function CBStartAudioUseSetting(mapargs)
  local value = gre.get_value("audio_use_selection_layer.use_group.items.text."..mapargs.context_row..".1")
  gre.set_value("mo_audio_use_setting.banner_heading", value)
  gre.set_value("audio_use_setting_layer.menu_items.port_id", mapargs.context_row - 1)
  ScreenTransition("mo_audio_use_setting")
end

-- Audio play back
local AUDIO_PROGRESS_INTERVAL = 250
local audio = {}

---
--- @brief  Callback to update the audio playback progress
local function CBAudioProgress()
  audio.current = audio.current + AUDIO_PROGRESS_INTERVAL

  if audio.current >= audio.duration then
    gre.timer_clear_interval(audio.progress_timer)
    audio.progress_timer = nil
    audio.current = audio.duration
  end
  local control = "home_tiles_layer.media_play_back_group.progress"
  local width = math.floor(gre.get_value(control..".grd_width") * audio.current / audio.duration + 0.5)
  gre.set_value(control..".slider_pos", width)
end

---
--- @brief  Callback to process the audio file that is playing event
--- @param gre#context mapargs
function CBProcessAudioFilePlaying(mapargs) 
  if mapargs.context_event_data.text == nil then
    return
  end

  local settings = assert(loadstring(mapargs.context_event_data.text))()
  if settings == nil then return end

  local group = "media_play_back_group"
  ActivateTile("media_play_back_group", true)

  group = "home_tiles_layer."..group
  
  local data = {}
  data[group..".file.channel_id"] = settings.channel_id
  
  local title = ""
  local sep = ""
  for _,item in ipairs(settings.play_list) do
    title = title..sep..item.title
    sep = ","
  end
  data[group..".file.text"] = title
  
  -- Calculate overal duration.
  local duration = 0
  for _,item in ipairs(settings.play_list) do
    if item.duration == nil then
      --terminate if duration is not available for one of the files.
      duration = nil
      break
    else
      duration = duration + item.duration
    end
  end
  if settings.duration == nil then
    data[group..".progress.grd_hidden"] = 1
    if audio.progress_timer ~= nil then
      gre.timer_clear_interval(audio.progress_timer)
      audio.progress_timer = nil
    end
  else
    data[group..".progress.slider_pos"] = 0
    data[group..".progress.grd_hidden"] = 0
    if audio.progress_timer == nil then
      audio.progress_timer = gre.timer_set_interval(CBAudioProgress, AUDIO_PROGRESS_INTERVAL)
    end
    audio.duration = settings.duration
    audio.current = 0
  end
  audio.channel_id = settings.channel_id
  
  gre.set_data(data)
end

---
--- @brief  Callback to process the audio file has stopped event
--- @param gre#context mapargs
function CBProcessAudioFileStopped(mapargs) 
  if mapargs.context_event_data.text == nil then
    return
  end
  local settings = assert(loadstring(mapargs.context_event_data.text))()
  if settings == nil then return end

  local group = "media_play_back_group"
  group = "home_tiles_layer."..group
  if audio.channel_id == settings.channel_id then
    if audio.progress_timer ~= nil then
      gre.timer_clear_interval(audio.progress_timer)
      audio.progress_timer = nil
    end
  end    
end

---
--- @brief  Process close audio tile action
--- @param gre#context mapargs
function CBCloseAudioTile(mapargs)
  if ScrollActive() then return end
  DeactivateTile("media_play_back_group")
end

---
--- @brief  Process play audio action
--- @param gre#context mapargs
function CBPlayAudio(mapargs) 
  if ScrollActive() then return end
  SendText("play_audio", "")
end

---
--- @brief  Process stop audio action
--- @param gre#context mapargs
function CBStopAudio(mapargs) 
  if ScrollActive() then return end
  SendText("stop_audio", "")
end

