components_login_UserSelect.bs

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

sub init()
  m.log = log.Logger("UserSelect")
  m.log.verbose("Initializing UserSelect component")

  m.top.optionsAvailable = false
  m.buttons = m.top.findNode("buttons")

  m.buttons.callFunc("center")

  ' Create branding config task (reusable instance)
  m.brandingTask = createObject("roSGNode", "BrandingConfigTask")
  m.log.debug("Created BrandingConfigTask")
end sub

sub itemContentChanged()
  stopLoadingSpinner()
  m.top.findNode("UserRow").ItemContent = m.top.itemContent
  redraw()
end sub

sub redraw()
  userCount = m.top.itemContent.Count()
  topBorder = 360
  leftBorder = 130
  itemWidth = 300
  itemSpacing = 40

  if userCount < 5
    leftBorder = (1920 - ((userCount * itemWidth) + ((userCount - 1) * itemSpacing))) / 2
  end if
  '   break()
  m.top.findNode("UserRow").translation = [leftBorder, topBorder]
end sub

' JRScreen hook called when the screen is displayed by the screen manager
sub OnScreenShown()
  m.log.info("UserSelect screen shown")

  scene = m.top.getScene()
  overhang = scene.findNode("overhang")
  if isValid(overhang)
    overhang.isLogoVisible = true
    overhang.currentUser = ""
    m.log.debug("Configured overhang for UserSelect")
  end if

  ' Load splashscreen (handles race condition)
  loadSplashscreen()
end sub

' JRScreen hook called when the screen is hidden by the screen manager
sub OnScreenHidden()
  m.log.info("UserSelect screen hidden - clearing backdrop")

  ' Stop task to prevent wasted resources
  m.brandingTask.control = "STOP"

  ' Cleanup observers and reset task
  m.global.server.unobserveFieldScoped("splashscreenEnabled")
  m.brandingTask.unobserveFieldScoped("responseCode")
  m.brandingTask.callFunc("empty")

  ' Clear backdrop using forceBackdrop to ensure it clears even before login
  m.global.sceneManager.callFunc("setBackgroundImage", "", true, true)
end sub

' Load splashscreen if enabled on server
' Always fetches fresh branding config from server
sub loadSplashscreen()
  m.log.info("Loading splashscreen - fetching branding config from server")

  ' Clear backdrop while waiting (forceBackdrop ensures it works before login)
  m.global.sceneManager.callFunc("setBackgroundImage", "", false, true)

  ' Check if value is already cached (from previous session)
  serverNode = m.global.server
  if isValid(serverNode.splashscreenEnabled)
    ' Already cached, apply immediately for instant display
    m.log.debug("Splashscreen setting already cached, applying immediately")
    applySplashscreen(serverNode.splashscreenEnabled)
  else
    m.log.debug("Splashscreen setting not cached")
  end if

  ' Always observe and refresh in case cached value is stale
  serverNode.observeFieldScoped("splashscreenEnabled", "onSplashscreenEnabledLoaded")
  m.brandingTask.observeFieldScoped("responseCode", "onBrandingConfigComplete")
  m.brandingTask.control = "RUN"
end sub

' Called when branding config task completes
sub onBrandingConfigComplete()
  responseCode = m.brandingTask.responseCode
  m.log.debug("Branding config fetch completed", "responseCode:", responseCode)

  if responseCode = 200
    m.log.info("Branding config cached successfully", "splashscreenEnabled:", m.global.server.splashscreenEnabled)
  else
    failureReason = m.brandingTask.failureReason
    m.log.warn("Branding config fetch failed", "reason:", failureReason)
  end if

  ' Cleanup task
  m.brandingTask.unobserveFieldScoped("responseCode")
  m.brandingTask.callFunc("empty")
end sub

' Called when branding config finishes loading (if we had to wait)
sub onSplashscreenEnabledLoaded()
  serverNode = m.global.server
  splashEnabled = serverNode.splashscreenEnabled

  m.log.debug("Branding config loaded (async)", "splashscreenEnabled:", splashEnabled)

  ' Unobserve (only fire once)
  serverNode.unobserveFieldScoped("splashscreenEnabled")

  ' Check validity again (defensive)
  if isValid(splashEnabled)
    applySplashscreen(splashEnabled)
  else
    m.log.warn("Branding config still invalid after loading - using default")
    ' Clear backdrop using forceBackdrop to ensure it works before login
    m.global.sceneManager.callFunc("setBackgroundImage", "", true, true)
  end if
end sub

' Apply splash background based on enabled flag
' Uses forceBackdrop parameter to show splashscreen before user login
sub applySplashscreen(serverSplashEnabled as boolean)
  ' Get global splash screen setting (reads from registry or settings.json default)
  ' This works before user login since global settings are device-wide
  globalSetting = getGlobalSplashScreenSetting()

  ' Resolve splash screen setting (JellyRock global override or server setting)
  splashEnabled = resolveSplashScreen(globalSetting, serverSplashEnabled)

  m.log.debug("Applying splashscreen", "globalSetting:", globalSetting, "serverSetting:", serverSplashEnabled, "resolvedValue:", splashEnabled)

  if splashEnabled = true
    ' Build splash URL with correct parameters
    splashUrl = buildURL("/Branding/Splashscreen", { "format": "jpg", "tag": "splash" })

    ' buildURL returns invalid when server URL is not configured
    if not isValid(splashUrl)
      m.log.warn("Cannot load splashscreen - server URL not configured")
      m.global.sceneManager.callFunc("setBackgroundImage", "", true, true)
      return
    end if

    m.log.info("Splashscreen enabled - loading", splashUrl)

    ' Set backdrop with animation, forceBackdrop=true bypasses user setting check
    m.global.sceneManager.callFunc("setBackgroundImage", splashUrl, true, true)
  else
    m.log.info("Splashscreen disabled - using default background")
    m.global.sceneManager.callFunc("setBackgroundImage", "", true, true)
  end if
end sub

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

  if key = "back"
    m.top.backPressed = true
    return true
  else if key = "up"
    if m.top.focusedChild.isSubType("JRButtonGroup")
      m.top.findNode("UserRow").setFocus(true)
      return true
    end if
  else if key = "down"
    if m.top.focusedChild.isSubType("UserRow")
      m.buttons.callFunc("focus")
      return true
    end if
  end if
  return false
end function