components_settings_settings.bs

import "pkg:/source/roku_modules/log/LogMixin.brs"
import "pkg:/source/utils/config.bs"
import "pkg:/source/utils/misc.bs"
' post device profile
import "pkg:/source/utils/deviceCapabilities.bs"

sub init()
  m.log = log.Logger("Settings")
  m.top.optionsAvailable = false

  m.userLocation = []

  m.settingsMenu = m.top.findNode("settingsMenu")
  m.settingDetail = m.top.findNode("settingDetail")
  m.settingDesc = m.top.findNode("settingDesc")
  m.path = m.top.findNode("path")

  m.boolSetting = m.top.findNode("boolSetting")
  m.integerSetting = m.top.findNode("integerSetting")
  m.radioSetting = m.top.findNode("radioSetting")

  m.integerSetting.observeField("submit", "onKeyGridSubmit")
  m.integerSetting.observeField("escape", "onKeyGridEscape")

  m.settingsMenu.setFocus(true)
  m.settingsMenu.observeField("itemFocused", "settingFocused")
  m.settingsMenu.observeField("itemSelected", "settingSelected")

  m.boolSetting.observeField("checkedItem", "boolSettingChanged")
  m.radioSetting.observeField("checkedItem", "radioSettingChanged")

  m.postTask = createObject("roSGNode", "PostTask")

  ' Load Configuration Tree
  m.configTree = GetConfigTree()
  LoadMenu({ children: m.configTree })
end sub

sub onKeyGridSubmit()
  selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
  set_user_setting(selectedSetting.settingName, m.integerSetting.text)
  m.settingsMenu.setFocus(true)
end sub

sub onKeyGridEscape()
  if m.integerSetting.escape = "left" or m.integerSetting.escape = "back"
    m.settingsMenu.setFocus(true)
  end if
end sub

sub LoadMenu(configSection)
  if configSection.children = invalid
    ' Load parent menu
    m.userLocation.pop()
    configSection = m.userLocation.peek()
  else
    if m.userLocation.Count() > 0 then m.userLocation.peek().selectedIndex = m.settingsMenu.itemFocused
    m.userLocation.push(configSection)
  end if

  result = CreateObject("roSGNode", "ContentNode")

  for each item in configSection.children
    listItem = result.CreateChild("ContentNode")
    listItem.title = tr(item.title)
    listItem.Description = tr(item.description)
    listItem.id = item.id
  end for

  m.settingsMenu.content = result

  if configSection.selectedIndex <> invalid and configSection.selectedIndex > -1
    m.settingsMenu.jumpToItem = configSection.selectedIndex
  end if

  ' Set Path display
  m.path.text = tr("Settings")
  for each level in m.userLocation
    if level.title <> invalid then m.path.text += " / " + tr(level.title)
  end for
end sub

sub settingFocused()

  selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
  m.settingDesc.text = tr(selectedSetting.Description)
  m.top.overhangTitle = tr(selectedSetting.Title)

  ' Hide Settings
  m.boolSetting.visible = false
  m.integerSetting.visible = false
  m.radioSetting.visible = false

  userSettings = m.global.session.user.settings

  if selectedSetting.type = invalid
    return
  else if selectedSetting.type = "bool"

    m.boolSetting.visible = true

    if userSettings[selectedSetting.settingName] = true
      m.boolSetting.checkedItem = 1
    else
      m.boolSetting.checkedItem = 0
    end if
  else if selectedSetting.type = "integer"
    integerValue = userSettings[selectedSetting.settingName].ToStr()
    if isValid(integerValue)
      m.integerSetting.text = integerValue
    end if
    m.integerSetting.visible = true
  else if LCase(selectedSetting.type) = "radio"

    selectedValue = userSettings[selectedSetting.settingName]

    radioContent = CreateObject("roSGNode", "ContentNode")

    itemIndex = 0
    for each item in m.userLocation.peek().children[m.settingsMenu.itemFocused].options
      listItem = radioContent.CreateChild("ContentNode")
      listItem.title = tr(item.title)
      listItem.id = item.id
      if selectedValue = item.id
        m.radioSetting.checkedItem = itemIndex
      end if
      itemIndex++
    end for

    m.radioSetting.content = radioContent

    m.radioSetting.visible = true
  else
    m.log.warn("Unknown setting type", selectedSetting.type)
  end if

end sub


sub settingSelected()

  selectedItem = m.userLocation.peek().children[m.settingsMenu.itemFocused]

  if selectedItem.type <> invalid ' Show setting
    if selectedItem.type = "bool"
      m.boolSetting.setFocus(true)
    end if
    if selectedItem.type = "integer"
      m.integerSetting.setFocus(true)
    end if
    if (selectedItem.type) = "radio"
      m.radioSetting.setFocus(true)
    end if
  else if selectedItem.children <> invalid and selectedItem.children.Count() > 0 ' Show sub menu
    LoadMenu(selectedItem)
    m.settingsMenu.setFocus(true)
  else
    return
  end if

  m.settingDesc.text = m.settingsMenu.content.GetChild(m.settingsMenu.itemFocused).Description

end sub


sub boolSettingChanged()
  if m.boolSetting.focusedChild = invalid then return
  selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]

  if m.boolSetting.checkedItem
    session.user.settings.Save(selectedSetting.settingName, "true")
    if Left(selectedSetting.settingName, 7) = "global."
      ' global user setting
      ' save to main registry block
      set_setting(selectedSetting.settingName, "true")
      ' setting specific triggers
      if selectedSetting.settingName = "global.rememberme"
        set_setting("active_user", m.global.session.user.id)
      end if
    else
      ' regular user setting
      ' save to user specific registry block
      set_user_setting(selectedSetting.settingName, "true")
    end if
  else
    session.user.settings.Save(selectedSetting.settingName, "false")
    if Left(selectedSetting.settingName, 7) = "global."
      ' global user setting
      ' save to main registry block
      set_setting(selectedSetting.settingName, "false")
      ' setting specific triggers
      if selectedSetting.settingName = "global.rememberme"
        unset_setting("active_user")
      end if
    else
      ' regular user setting
      ' save to user specific registry block
      set_user_setting(selectedSetting.settingName, "false")
    end if
  end if
end sub

sub radioSettingChanged()
  if m.radioSetting.focusedChild = invalid then return
  selectedSetting = m.userLocation.peek().children[m.settingsMenu.itemFocused]
  set_user_setting(selectedSetting.settingName, m.radioSetting.content.getChild(m.radioSetting.checkedItem).id)
end sub

' JRScreen hook that gets ran as needed.
' Assumes settings were changed and they affect the device profile.
' Posts a new device profile to the server using the task thread
sub OnScreenHidden()
  m.postTask.arrayData = getDeviceCapabilities()
  m.postTask.apiUrl = "/Sessions/Capabilities/Full"
  m.postTask.control = "RUN"
  m.postTask.observeField("responseCode", "postFinished")
end sub

' Triggered by m.postTask after completing a post.
' Empty the task data when finished.
sub postFinished()
  m.postTask.unobserveField("responseCode")
  m.postTask.callFunc("empty")
end sub

' Returns true if any of the data entry forms are in focus
function isFormInFocus() as boolean
  if isValid(m.settingDetail.focusedChild) or m.radioSetting.hasFocus() or m.boolSetting.hasFocus() or m.integerSetting.hasFocus()
    return true
  end if
  return false
end function

function onKeyEvent(key as string, press as boolean) as boolean
  if not press then return false

  if (key = "back" or key = "left") and m.settingsMenu.focusedChild <> invalid and m.userLocation.Count() > 1
    LoadMenu({})
    return true
  else if (key = "back" or key = "left") and isFormInFocus()
    m.settingsMenu.setFocus(true)
    return true
  end if

  if key = "options"
    m.global.sceneManager.callFunc("popScene")
    return true
  end if

  if key = "right"
    settingSelected()
  end if

  if key = "up" and m.settingsMenu.focusedChild <> invalid and m.settingsMenu.itemFocused = 0
    m.settingsMenu.jumpToItem = m.settingsMenu.content.getChildCount() - 1

    return true
  end if

  if key = "down" and m.settingsMenu.focusedChild <> invalid
    if m.settingsMenu.itemFocused = m.settingsMenu.content.getChildCount() - 1
      m.settingsMenu.jumpToItem = 0

      return true
    end if
  end if

  return false
end function