content: ' Copyright (c) 2018 Roku, Inc. All rights reserved.
  
  sub init()
      m.debug = false
      m.currentFocusedNode = invalid
      m.top.observeField("focusedChild", "onFocusedChild")
      m.top.observeField("layoutDirection", "layoutChanged")
      layoutChanged()
  end sub
  
  Sub onFocusedChild()
      if m.top.hasFocus()
          foc = m.top.focusedChild
          if m.debug AND foc <> invalid then ?"focused now="foc.id
          if m.currentFocusedNode = invalid ANd m.top.getchildCount() > 0 AND (m.top.focusedChild = invalid OR m.top.issameNode(m.top.focusedChild))
              firstFocusableChild = GetFirstFocusable(0, 1)
              if m.debug then ?"set focus to first focusable"
              if firstFocusableChild <> invalid
                  if m.debug then ?"firstFocusableChild.setFocus(true)"
                  firstFocusableChild.setFocus(true)
              end if
          else if m.currentFocusedNode <> invalid and m.top.isInFocusChain() and not m.currentFocusedNode.hasFocus()
              m.currentFocusedNode.setFocus(true)
              if m.debug then ?"m.currentFocusedNode.setFocus(true)"
          end if
      end if
  
      if m.currentFocusedNode = invalid OR (m.top.focusedChild <> invalid AND NOT m.currentFocusedNode.isSameNode(m.top.focusedChild))
          if m.debug then ?"set current focused node"m.top.focusedChild.id
          m.currentFocusedNode = m.top.focusedChild
      end if
  end Sub
  
  Sub layoutChanged()
      if m.top.layoutDirection = "vert"
          m.buttonsTohandle = {up : -1, down : 1}
      else
          m.buttonsTohandle = {right : 1,left : -1}
      end if
  end sub
  
  function onKeyEvent(key as String, press as Boolean) as Boolean
      handled = false
  
      if press AND m.currentFocusedNode <> invalid AND m.buttonsTohandle[key] <> invalid
          if m.top.getchildCount() > 0 then
              childCount = m.top.getchildCount()
              for index = 0 to childCount - 1
                  child = m.top.getChild(index)
                  if child <> invalid AND m.currentFocusedNode.isSameNode(child)
                      indexToMove = index + m.buttonsTohandle[key]
                      if m.debug then
                          ?"!index="index
                          ?"!indexToMove="indexToMove
                      end if
                      if (indexToMove >= 0 AND indexToMove < childCount) or m.top.allowCarousel
                          if indexToMove < 0 then
                              index = childCount - 1
                          else if indexToMove >= childCount
                              index = 0
                          end if
  
                          newchild = GetFirstFocusable(index, m.buttonsTohandle[key])
  
                          if m.debug then
                              if newchild <> invalid
                                  ?"newFocus:"newchild.subType() " id="newchild.id
                              else
                                  ?"focused child not found"
                              end if
                          end if
  
                          if newchild <> invalid AND (m.currentFocusedNode = invalid OR not m.currentFocusedNode.isSameNode(newchild))
                              if m.currentFocusedNode <> invalid
                                  m.currentFocusedNode.setFocus(false)
                              end if
                              m.currentFocusedNode = newchild
                              newchild.setFocus(true)
                              handled = true
                          end if
                      end if
                      exit for
                  end if
              end for
          end if
      else if press
          if key = "OK"          
          end if
      end if
      return handled
  end function
  
  function GetFirstFocusable(startIndex, stepIndex)
      if m.debug
          ?"startIndex:"startIndex
          ?"stepIndex:"stepIndex
      end if
  
      index = startIndex
  
      while(index >= 0 AND index < m.top.getChildCount())
          index = index + stepIndex
  
          child = m.top.getChild(index)
          if child <> invalid AND child.focusable
              return child
          end if
      end while
  
      child = m.top.getChild(startIndex)
      if child <> invalid then return child
      return invalid
  end function
  
  
  