components_ItemGrid_ItemGridOptions.bs

import "pkg:/source/roku_modules/log/LogMixin.brs"
import "pkg:/source/utils/misc.bs"

sub init()
  m.log = log.Logger("ItemGridOptions")
  m.buttons = m.top.findNode("buttons")
  m.buttons.buttons = [tr("View"), tr("Sort"), tr("Filter")]
  m.buttons.selectedIndex = 1
  m.buttons.setFocus(true)

  m.favoriteMenu = m.top.findNode("favoriteMenu")
  m.selectedFavoriteItem = m.top.findNode("selectedFavoriteItem")

  m.selectedSortIndex = 0
  m.selectedItem = 1

  m.menus = []
  m.menus.push(m.top.findNode("viewMenu"))
  m.menus.push(m.top.findNode("sortMenu"))
  m.menus.push(m.top.findNode("filterMenu"))

  m.filterOptions = m.top.findNode("filterOptions")

  m.filterMenu = m.top.findNode("filterMenu")
  m.filterMenu.observeField("itemFocused", "onFilterFocusChange")

  m.viewNames = []
  m.sortNames = []
  m.filterNames = []

  ' Animation
  m.fadeAnim = m.top.findNode("fadeAnim")
  m.fadeOutAnimOpacity = m.top.findNode("outOpacity")
  m.fadeInAnimOpacity = m.top.findNode("inOpacity")
  m.showChecklistAnimation = m.top.findNode("showChecklistAnimation")
  m.hideChecklistAnimation = m.top.findNode("hideChecklistAnimation")

  m.buttons.observeField("focusedIndex", "buttonFocusChanged")
  m.favoriteMenu.observeField("buttonSelected", "toggleFavorite")
end sub

sub showChecklist()
  if m.filterOptions.opacity = 0
    if m.showChecklistAnimation.state = "stopped"
      m.showChecklistAnimation.control = "start"
    end if
  end if
end sub

sub hideChecklist()
  if m.filterOptions.opacity = 1
    if m.hideChecklistAnimation.state = "stopped"
      m.hideChecklistAnimation.control = "start"
    end if
  end if
end sub

sub onFilterFocusChange()
  if not isFilterMenuDataValid()
    hideChecklist()
    return
  end if

  if m.filterMenu.content.getChild(m.filterMenu.itemFocused).getChildCount() > 0
    showChecklist()
  else
    hideChecklist()
  end if

  m.filterOptions.content = m.filterMenu.content.getChild(m.filterMenu.itemFocused)
  if isValid(m.filterMenu.content.getChild(m.filterMenu.itemFocused).checkedState)
    m.filterOptions.checkedState = m.filterMenu.content.getChild(m.filterMenu.itemFocused).checkedState
  else
    m.filterOptions.checkedState = []
  end if
end sub

' Check if data for Filter Menu is valid
function isFilterMenuDataValid() as boolean
  if not isValid(m.filterMenu) or not isValid(m.filterMenu.content) or not isValid(m.filterMenu.itemFocused)
    return false
  end if

  if not isValid(m.filterMenu.content.getChild(m.filterMenu.itemFocused))
    return false
  end if

  return true
end function

sub optionsSet()
  '  Views Tab
  if m.top.options.views <> invalid
    viewContent = CreateObject("roSGNode", "ContentNode")
    index = 0
    selectedViewIndex = m.selectedViewIndex

    for each view in m.top.options.views
      entry = viewContent.CreateChild("ContentNode")
      entry.title = view.Title
      m.viewNames.push(view.Name)
      if (view.selected <> invalid and view.selected = true) or viewContent.Name = m.top.view
        selectedViewIndex = index
      end if
      index = index + 1
    end for
    m.menus[0].content = viewContent
    m.menus[0].checkedItem = selectedViewIndex
  end if

  ' Sort Tab
  if m.top.options.sort <> invalid
    sortContent = CreateObject("roSGNode", "ContentNode")
    index = 0
    m.selectedSortIndex = 0

    for each sortItem in m.top.options.sort
      entry = sortContent.CreateChild("ContentNode")
      entry.title = sortItem.Title
      m.sortNames.push(sortItem.Name)
      if sortItem.Selected <> invalid and sortItem.Selected = true
        m.selectedSortIndex = index
        if sortItem.Ascending <> invalid and sortItem.Ascending = false
          m.top.sortAscending = 0
        else
          m.top.sortAscending = 1
        end if
      end if
      index = index + 1
    end for
    m.menus[1].content = sortContent
    m.menus[1].checkedItem = m.selectedSortIndex

    globalConstants = m.global.constants
    if m.top.sortAscending = 1
      m.menus[1].focusedCheckedIconUri = globalConstants.icons.arrow_up_black
      m.menus[1].checkedIconUri = globalConstants.icons.arrow_up_white
    else
      m.menus[1].focusedCheckedIconUri = globalConstants.icons.arrow_down_black
      m.menus[1].checkedIconUri = globalConstants.icons.arrow_down_white
    end if
  end if

  ' Filter Tab
  if m.top.options.filter <> invalid
    filterContent = CreateObject("roSGNode", "ContentNode")
    index = 0
    m.selectedFilterIndex = 0

    for each filterItem in m.top.options.filter
      entry = filterContent.CreateChild("OptionNode")
      entry.title = filterItem.Title
      entry.name = filterItem.Name
      entry.delimiter = filterItem.Delimiter

      if isValid(filterItem.options)
        for each filterItemOption in filterItem.options
          entryOption = entry.CreateChild("ContentNode")
          entryOption.title = toString(filterItemOption)
        end for
        entry.checkedState = filterItem.checkedState
      end if

      m.filterNames.push(filterItem.Name)
      if filterItem.selected <> invalid and filterItem.selected = true
        m.selectedFilterIndex = index
      end if
      index = index + 1
    end for
    m.menus[2].content = filterContent
    m.menus[2].checkedItem = m.selectedFilterIndex
  else
    filterContent = CreateObject("roSGNode", "ContentNode")
    entry = filterContent.CreateChild("ContentNode")
    entry.title = "All"
    m.filterNames.push("All")
    m.menus[2].content = filterContent
    m.menus[2].checkedItem = 0
  end if
end sub

' Switch menu shown when button focus changes
sub buttonFocusChanged()
  if m.buttons.focusedIndex = m.selectedItem
    if m.buttons.hasFocus()
      m.buttons.setFocus(false)
      m.menus[m.selectedItem].setFocus(false)
      m.menus[m.selectedItem].visible = false
      m.favoriteMenu.setFocus(true)
    end if
  end if
  m.fadeOutAnimOpacity.fieldToInterp = m.menus[m.selectedItem].id + ".opacity"
  m.fadeInAnimOpacity.fieldToInterp = m.menus[m.buttons.focusedIndex].id + ".opacity"
  m.fadeAnim.control = "start"
  m.selectedItem = m.buttons.focusedIndex
end sub

sub toggleFavorite()
  if not isValid(m.selectedFavoriteItem) then return

  m.favItemsTask = createObject("roSGNode", "FavoriteItemsTask")
  if m.favoriteMenu.iconUri = "pkg:/images/icons/favorite.png"
    m.favoriteMenu.iconUri = "pkg:/images/icons/favorite_selected.png"
    m.favoriteMenu.focusedIconUri = "pkg:/images/icons/favorite_selected.png"
    ' Run the task to actually favorite it via API
    m.favItemsTask.favTask = "Favorite"
    m.favItemsTask.itemId = m.selectedFavoriteItem.id
    m.favItemsTask.control = "RUN"
  else
    m.favoriteMenu.iconUri = "pkg:/images/icons/favorite.png"
    m.favoriteMenu.focusedIconUri = "pkg:/images/icons/favorite.png"
    m.favItemsTask.favTask = "Unfavorite"
    m.favItemsTask.itemId = m.selectedFavoriteItem.id
    m.favItemsTask.control = "RUN"
  end if
  ' Make sure we set the Favorite Heart color for the appropriate child
  setHeartColor("#cc3333")
end sub

sub setHeartColor(color as string)
  try
    for i = 0 to 6
      node = m.favoriteMenu.getChild(i)
      if node <> invalid and node.uri <> invalid and node.uri = "pkg:/images/icons/favorite_selected.png"
        m.favoriteMenu.getChild(i).blendColor = color
      end if
    end for
  catch e
    m.log.error("setHeartColor()", e.number, e.message)
  end try
end sub

sub saveFavoriteItemSelected(msg)
  data = msg.GetData()
  m.selectedFavoriteItem = data
  ' Favorite button
  if m.selectedFavoriteItem <> invalid
    if m.selectedFavoriteItem.favorite = true
      m.favoriteMenu.iconUri = "pkg:/images/icons/favorite_selected.png"
      m.favoriteMenu.focusedIconUri = "pkg:/images/icons/favorite_selected.png"
      ' Make sure we set the Favorite Heart color for the appropriate child
      setHeartColor("#cc3333")
    else
      m.favoriteMenu.iconUri = "pkg:/images/icons/favorite.png"
      m.favoriteMenu.focusedIconUri = "pkg:/images/icons/favorite.png"
      ' Make sure we set the Favorite Heart color for the appropriate child
      setHeartColor("#cc3333")
    end if
  end if
end sub

function onKeyEvent(key as string, press as boolean) as boolean
  if key = "down" or (key = "OK" and m.buttons.hasFocus())
    m.buttons.setFocus(false)
    m.menus[m.selectedItem].setFocus(true)
    m.menus[m.selectedItem].drawFocusFeedback = true

    'If user presses down from button menu, focus first item.  If OK, focus checked item
    if key = "down"
      m.menus[m.selectedItem].jumpToItem = 0
    else
      m.menus[m.selectedItem].jumpToItem = m.menus[m.selectedItem].itemSelected
    end if

    return true
  else if key = "right"
    if not isFilterMenuDataValid() then return false

    if m.menus[m.selectedItem].isInFocusChain()
      ' Handle Filter screen
      if m.selectedItem = 2
        ' Selected filter has options, move cursor to it
        if m.filterMenu.content.getChild(m.filterMenu.itemFocused).getChildCount() > 0
          m.menus[m.selectedItem].setFocus(false)
          m.filterOptions.setFocus(true)
          return true
        end if
      end if
    end if
  else if key = "left"
    if m.favoriteMenu.hasFocus()
      m.favoriteMenu.setFocus(false)
      m.menus[m.selectedItem].visible = true
      m.buttons.setFocus(true)
    end if

    ' User wants to escape filter options
    if m.filterOptions.isInFocusChain()
      m.filterOptions.setFocus(false)
      m.menus[m.selectedItem].setFocus(true)
      return true
    end if
  else if key = "OK"

    if m.menus[m.selectedItem].isInFocusChain()
      ' Handle View Screen
      if m.selectedItem = 0
        m.selectedViewIndex = m.menus[0].itemSelected
        m.top.view = m.viewNames[m.selectedViewIndex]
      end if

      ' Handle Sort screen
      if m.selectedItem = 1
        globalConstants = m.global.constants

        if m.menus[1].itemSelected <> m.selectedSortIndex
          m.menus[1].focusedCheckedIconUri = globalConstants.icons.arrow_up_black
          m.menus[1].checkedIconUri = globalConstants.icons.arrow_up_white

          m.selectedSortIndex = m.menus[1].itemSelected
          m.top.sortAscending = true
          m.top.sortField = m.sortNames[m.selectedSortIndex]
        else

          if m.top.sortAscending = true
            m.top.sortAscending = false
            m.menus[1].focusedCheckedIconUri = globalConstants.icons.arrow_down_black
            m.menus[1].checkedIconUri = globalConstants.icons.arrow_down_white
          else
            m.top.sortAscending = true
            m.menus[1].focusedCheckedIconUri = globalConstants.icons.arrow_up_black
            m.menus[1].checkedIconUri = globalConstants.icons.arrow_up_white
          end if
        end if
      end if

      ' Handle Filter screen
      if m.selectedItem = 2
        if not isFilterMenuDataValid() then return false
        ' If filter has no options, select it
        if m.filterMenu.content.getChild(m.filterMenu.itemFocused).getChildCount() = 0
          m.menus[2].checkedItem = m.menus[2].itemSelected
          m.selectedFilterIndex = m.menus[2].itemSelected
          m.top.filter = m.filterNames[m.selectedFilterIndex]
          m.top.filterOptions = {}
          return true
        end if

        ' Selected filter has options, move cursor to it
        m.filterOptions.setFocus(true)
        m.menus[m.selectedItem].setFocus(false)
        return true
      end if
    end if

    ' User pressed OK from inside the filter's options
    if m.filterOptions.isInFocusChain()
      selectedOptions = []
      for i = 0 to m.filterOptions.checkedState.count() - 1
        if m.filterOptions.checkedState[i]
          selectedValue = toString(m.filterOptions.content.getChild(i).title)
          selectedOptions.push(selectedValue)
        end if
      end for

      if selectedOptions.Count() > 0
        m.menus[2].checkedItem = m.menus[2].itemFocused
        m.selectedFilterIndex = m.menus[2].itemFocused
        m.top.filter = m.filterMenu.content.getChild(m.filterMenu.itemFocused).Name

        newFilter = {}
        newFilter[m.top.filter] = selectedOptions.join(m.filterMenu.content.getChild(m.filterMenu.itemFocused).delimiter)
        m.top.filterOptions = newFilter
      else
        m.menus[2].checkedItem = 0
        m.selectedFilterIndex = 0
        m.top.filter = m.filterNames[0]
        m.top.filterOptions = {}
      end if

      m.filterMenu.content.getChild(m.filterMenu.itemFocused).checkedState = m.filterOptions.checkedState

      return true
    end if
    return true
  else if key = "back" or key = "up"
    if key = "back" then hideChecklist()

    m.menus[2].visible = true ' Show Filter contents in case hidden by favorite button
    if m.menus[m.selectedItem].isInFocusChain()
      m.buttons.setFocus(true)
      m.menus[m.selectedItem].drawFocusFeedback = false
      return true
    end if
  else if key = "options"
    hideChecklist()
    m.menus[2].visible = true ' Show Filter contents in case hidden by favorite button
    m.menus[m.selectedItem].drawFocusFeedback = false
    return false
  end if

  return false
end function