local UI = game.UI
local ErrorOnUnknownAsset = false
local Enabled = function()
  return UI.GetEnabled()
end
local EventHandlerPrefix = "EVT_"
local SLI_FLOAT_TYPE = 0
local SLI_INT_TYPE = 1
local SLI_BOOL_TYPE = 2
local SLI_STRING_TYPE = 3
local SLI_UNKNOWN_TYPE = 8
local Type2SliType = {
  number = SLI_FLOAT_TYPE,
  boolean = SLI_BOOL_TYPE,
  string = SLI_STRING_TYPE
}
local GetSliType = function(var)
  local sliType = Type2SliType[type(var)]
  if sliType then
    return sliType
  end
  return SLI_UNKNOWN_TYPE
end
local type2setter = {}
type2setter[SLI_FLOAT_TYPE] = UI.SetStateVarFloat
type2setter[SLI_INT_TYPE] = UI.SetStateVarInt
type2setter[SLI_BOOL_TYPE] = UI.SetStateVarBoolean
type2setter[SLI_STRING_TYPE] = UI.SetStateVarString
local PublishValue = function(name, value)
  local type_ = GetSliType(value)
  type2setter[type_](name, value)
end
local IsStringNilOrEmpty = function(string)
  return string == nil or string == ""
end
local SetGameObjectAlpha = function(gameObj, alphaValue, material, layer, attribute)
  assert(gameObj ~= nil and alphaValue ~= nil and material ~= nil and layer ~= nil and attribute ~= nil, "nil parameter was passed into lua util function. UI::Util::SetGameObjectAlpha.")
  local materialEntry = gameObj:GetMaterialEntry(material, layer .. "." .. attribute)
  materialEntry.Value = alphaValue
end
local SetGameObjectColor = function(gameObj, color, material, layer, attribute)
  if gameObj ~= nil and color ~= nil and material ~= nil and layer ~= nil and attribute ~= nil then
    local materialEntry = gameObj:GetMaterialEntry(material, layer .. "." .. attribute)
    materialEntry.Value = engine.Vector.New(color[1], color[2], color[3])
  end
end
local SetColor = function(objName, color, material, layer, attribute)
  if objName ~= nil then
    local obj = ActiveLevel:FindGameObjects(objName)
    for _, val in ipairs(obj) do
      SetGameObjectColor(val, color, material, layer, attribute)
    end
  end
end
local InstallEventHooks = function(hooks, obj, eventNames, eventHandler)
  for _, eventName in ipairs(eventNames) do
    local token = hooks.InstallWithMachineIndex(eventName, obj._state:GetMachineIndex(), function()
      eventHandler(obj)
    end)
    assert(nil == obj._hookTokens[eventName])
    obj._hookTokens[eventName] = token
  end
end
local UninstallEventHooks = function(hooks, obj, eventNames)
  for _, eventName in ipairs(eventNames) do
    hooks.UninstallWithMachineIndex(eventName, obj._state:GetMachineIndex(), obj._hookTokens[eventName])
  end
end
local SetScreenspacePos = function(goName, x, y)
  UI.SetGOScreenspacePos(goName, x, y)
end
local IsInCombat = function()
  local targeted = false
  local sonTargeted = false
  local bboard = game.Player.FindPlayer():GetBlackboard()
  if bboard then
    targeted = bboard:GetBoolean("TargetedByEnemy") == true
    sonTargeted = bboard:GetBoolean("SonTargetedByEnemy") == true
  end
  return targeted or sonTargeted
end
local InPlaytestMode = function()
  return game.InPlaytestMode ~= nil and game.InPlaytestMode()
end
local CallScriptOnGameObject = function(objectName, functionName, ...)
  assert(functionName ~= nil, "Function name passed was nil.")
  local player = game.Player.FindPlayer()
  local interactObj = player:GetCurrentInteractObject()
  if interactObj ~= nil and interactObj:GetName() == objectName then
    interactObj:CallScript(functionName, ...)
  end
end
local CallScriptOnCurrentInteractObject = function(functionName, ...)
  assert(functionName ~= nil, "Function name passed was nil.")
  local player = game.Player.FindPlayer()
  local interactObj = player:GetCurrentInteractObject()
  if interactObj ~= nil then
    interactObj:CallScript(functionName, ...)
  end
end
local GetLAMSMsg = function(lamsID, itemRef)
  local msg = ""
  local messageFound = false
  if lamsID ~= nil then
    local lamsMsg = "[MSG:" .. lamsID .. "]"
    if lamsMsg ~= nil then
      msg = lamsMsg
      messageFound = true
      local showSourceText = engine.VFSGetBool("/UI/Text/Show Source Text") == 1
      if showSourceText and not IsStringNilOrEmpty(itemRef) then
        msg = tostring(itemRef) .. " " .. msg
      end
    end
  end
  if messageFound == false then
    msg = "LAMS ID " .. tostring(lamsID) .. " Not Found"
  end
  return msg, messageFound
end
local GetLAMSStringFromMsg = function(lamsMSG)
  local lamsID = string.match(lamsMSG, "%d+")
  local msg = lamsMSG
  if lamsID ~= nil then
    msg = UI.GetLAMSMsg(lamsID)
  end
  return msg
end
local FormatLAMSString = function(lamsID, ...)
  local msg = ""
  local messageFound = false
  if lamsID ~= nil then
    local lamsMsg = UI.GetLAMSMsg(lamsID)
    if lamsMsg ~= nil then
      msg = string.format(lamsMsg, unpack({
        ...
      }))
      messageFound = true
    end
  end
  if messageFound == false then
    msg = "LAMS ID " .. tostring(lamsID) .. " Not Found"
  end
  return msg, messageFound
end
local cineNum_SonSickStart = 365
local cineNum_SonSickEnd = 390
local SonUI_ShouldShow = function()
  local sonref = game.AI.FindSon()
  local shouldShow = false
  if sonref ~= nil then
    shouldShow = sonref:IsAvailableInLevel()
  end
  local cineNum = game.Level.GetVariable("CompletedCineNumber")
  shouldShow = shouldShow and (cineNum < cineNum_SonSickStart or cineNum >= cineNum_SonSickEnd)
  return shouldShow
end
local SonUI_ShouldDisable = function()
  local sonref = game.AI.FindSon()
  local shouldDisable = true
  if sonref ~= nil then
    shouldDisable = not sonref:IsAvailableForCombat()
  end
  return shouldDisable
end
local IsMenuSelectionAvailable = function(isBladesSelection, hasBlades, isSonSelection)
  return not isSonSelection and not isBladesSelection or isBladesSelection and hasBlades or isSonSelection and SonUI_ShouldShow()
end
local IsMenuSelectionFocusable = function(isBladesSelection, hasBlades, isSonSelection)
  return not isSonSelection and not isBladesSelection or isBladesSelection and hasBlades or isSonSelection and not SonUI_ShouldDisable()
end
local StringLengthUTF8 = function(text)
  local _, count = string.gsub(text, "[^\128-\193]", "")
  return count
end
local CharLengthUTF8 = function(char)
  if not char then
    return 0
  elseif 240 < char then
    return 4
  elseif 225 < char then
    return 3
  elseif 192 < char then
    return 2
  else
    return 1
  end
end
local SubUTF8 = function(str, startChar, numChars)
  local startIndex = 1
  while 1 < startChar do
    local char = string.byte(str, startIndex)
    startIndex = startIndex + CharLengthUTF8(char)
    startChar = startChar - 1
  end
  local currentIndex = startIndex
  while 0 < numChars and currentIndex <= #str do
    local char = string.byte(str, currentIndex)
    currentIndex = currentIndex + CharLengthUTF8(char)
    numChars = numChars - 1
  end
  return str:sub(startIndex, currentIndex - 1)
end
local Clamp = function(n, low, high)
  return math.min(math.max(n, low), high)
end
local Truncate = function(n)
  return n < 0 and math.ceil(n) or math.floor(n)
end
local Round = function(val)
  local fract = val % 1
  if fract < 0.5 then
    return math.floor(val)
  else
    return math.ceil(val)
  end
end
local function DebugPrintTable(state, table)
  if state ~= nil then
    local s = [[

table: ]] .. tostring(table)
    if table ~= nil and type(table) == "table" then
      s = s .. ", #table: " .. tostring(#table)
      for k, v in pairs(table) do
        s = s .. [[

	k: ]] .. tostring(k) .. ", v: "
        if type(v) == "table" then
          DebugPrintTable(state, v)
        else
          s = s .. tostring(v)
        end
      end
    end
    state:DebugPrint(s)
  else
    print("DebugPrintTable failed because state was nil.")
  end
end
local PrintTable = function(table)
  local s = [[

table: ]] .. tostring(table)
  if table ~= nil and type(table) == "table" then
    s = s .. ", #table: " .. tostring(#table)
    for k, v in pairs(table) do
      s = s .. [[

	k: ]] .. tostring(k) .. ", v: " .. tostring(v)
    end
  end
  print(s)
end
local uiCache = {}
uiCache.dict = {}
uiCache.level = nil
uiCache.objs = {}
local OnScriptLoaded = function(level)
  uiCache.level = level
end
local DoShowHide = function(show, isRecursive, ...)
  local objs = uiCache.objs
  local cacheDict = uiCache.dict
  local numObjs = 0
  for _, name in ipairs({
    ...
  }) do
    local obj = cacheDict[name]
    if obj == nil then
      obj = uiCache.level:FindSingleGameObject(name)
      cacheDict[name] = obj
      if obj == nil and ErrorOnUnknownAsset then
        error("unknown UI asset: " .. name)
      end
    end
    if obj then
      numObjs = numObjs + 1
      objs[numObjs] = obj
    end
  end
  if 0 < numObjs then
    if show then
      if isRecursive and UI.ShowObjsRecursive then
        UI.ShowObjsRecursive(objs)
      else
        UI.ShowObjs(objs)
      end
    else
      UI.HideObjs(objs)
    end
    for i = 1, numObjs do
      objs[i] = nil
    end
  end
end
local ShowRecursive = function(...)
  DoShowHide(true, true, ...)
end
local Show = function(...)
  DoShowHide(true, false, ...)
end
local Hide = function(...)
  engine.ProfileCall("Hide", DoShowHide, false, false, ...)
end
local GetUiObjByName = function(name)
  if name == nil then
    return nil
  end
  return uiCache.level:FindSingleGameObject(name)
end
local GetGOFromChildrenByName = function(goRoot, name)
  assert(goRoot ~= nil, "GetChildGOByName called with no root game object!")
  assert(not IsStringNilOrEmpty(name), "GetChildGOByName called with no game object name!")
  local gameObject
  local nameLowercase = string.lower(name)
  for _, goChild in ipairs(goRoot.Children) do
    local childName = goChild:GetName()
    if childName == nameLowercase then
      gameObject = goChild
      break
    end
  end
  return gameObject
end
local GetValueWithDefault = function(value, default)
  local v = default
  if value ~= nil then
    v = value
  end
  return v
end
local ForceUICreatureMove = function(creatureName, moveName)
  local uiCreature = UI.FindCreatureByGOName(creatureName)
  if uiCreature ~= nil then
    UI.ForceMove(uiCreature, moveName)
  end
end
local GetPauseMenuCameraObject = function()
  local uiCamObj = GetUiObjByName("pauseCamera")
  uiCamObj = uiCamObj:FindSingleGOByName("uiCamera_pause")
  uiCamObj = uiCamObj:FindSingleGOByName("uiCamera00")
  return uiCamObj
end
local GetTextHandle = function(gameObject, objectName)
  if objectName == nil then
    return UI.TextObject(gameObject)
  else
    return UI.TextObject(gameObject, objectName)
  end
end
local StyleText = function(text, style)
  assert(text ~= nil and type(text) == "string", "Text passed into Util:StyleText was an improper argument. Value was: " .. tostring(text))
  assert(style ~= nil and type(style) == "string", "Style passed into Util:StyleText was an improper argument. Value was: " .. tostring(style))
  return "<" .. style .. ">" .. text .. "</" .. style .. ">"
end
local automationPrintFunction
local UIAutomationPrint = function(string)
  if automationPrintFunction ~= nil then
    print(string)
  end
end
local EnableUIAutomationPrintouts = function(enable)
  if enable then
    automationPrintFunction = UIAutomationPrint
  else
    automationPrintFunction = nil
  end
end
local InternationalizeTime = function(timeString)
  local separator = GetLAMSMsg(43719)
  return string.gsub(timeString, "[.]", separator)
end
local HandleDisplaySetting = function(setting)
  return setting ~= 0 and (setting ~= 2 or not not _G.touchPad)
end
return {
  Enabled = Enabled,
  EventHandlerPrefix = EventHandlerPrefix,
  GetSliType = GetSliType,
  PublishValue = PublishValue,
  IsStringNilOrEmpty = IsStringNilOrEmpty,
  SetGameObjectAlpha = SetGameObjectAlpha,
  SetGameObjectColor = SetGameObjectColor,
  SetColor = SetColor,
  InstallEventHooks = InstallEventHooks,
  UninstallEventHooks = UninstallEventHooks,
  SetScreenspacePos = SetScreenspacePos,
  IsInCombat = IsInCombat,
  InPlaytestMode = InPlaytestMode,
  CallScriptOnGameObject = CallScriptOnGameObject,
  CallScriptOnCurrentInteractObject = CallScriptOnCurrentInteractObject,
  GetLAMSMsg = GetLAMSMsg,
  GetLAMSStringFromMsg = GetLAMSStringFromMsg,
  FormatLAMSString = FormatLAMSString,
  SonUI_ShouldShow = SonUI_ShouldShow,
  SonUI_ShouldDisable = SonUI_ShouldDisable,
  IsMenuSelectionAvailable = IsMenuSelectionAvailable,
  IsMenuSelectionFocusable = IsMenuSelectionFocusable,
  StringLengthUTF8 = StringLengthUTF8,
  CharLengthUTF8 = CharLengthUTF8,
  SubUTF8 = SubUTF8,
  Clamp = Clamp,
  Truncate = Truncate,
  Round = Round,
  DebugPrintTable = DebugPrintTable,
  PrintTable = PrintTable,
  SLI_FLOAT_TYPE = SLI_FLOAT_TYPE,
  SLI_INT_TYPE = SLI_INT_TYPE,
  SLI_BOOL_TYPE = SLI_BOOL_TYPE,
  SLI_STRING_TYPE = SLI_STRING_TYPE,
  SLI_UNKNOWN_TYPE = SLI_UNKNOWN_TYPE,
  OnScriptLoaded = OnScriptLoaded,
  Show = Show,
  ShowRecursive = ShowRecursive,
  Hide = Hide,
  GetUiObjByName = GetUiObjByName,
  GetGOFromChildrenByName = GetGOFromChildrenByName,
  GetValueWithDefault = GetValueWithDefault,
  ForceUICreatureMove = ForceUICreatureMove,
  GetPauseMenuCameraObject = GetPauseMenuCameraObject,
  GetTextHandle = GetTextHandle,
  StyleText = StyleText,
  UIAutomationPrint = UIAutomationPrint,
  EnableUIAutomationPrintouts = EnableUIAutomationPrintouts,
  InternationalizeTime = InternationalizeTime,
  HandleDisplaySetting = HandleDisplaySetting
}
