local classlib = require("core.class")
local consts = require("ui.consts")
local fsm = require("ui.fsm")
local hudConsts = require("ui.hudConsts")
local util = require("ui.util")
local priorityList = require("ui.priorityList")
local timer = require("level.timer")
local uiCalls = require("ui.uicalls")
local Compass = game.Compass
local UI = game.UI
local MainHUD = classlib.Class("MainHUD", fsm.UIState)
local mainHUD = MainHUD.New("mainHUD", {})
function MainHUD:HandleDisplaySetting(setting)
  if setting == 0 or setting == 2 and not self.touchPad then
    return false
  else
    return nil
  end
end
function MainHUD:Setup()
  self.mainHUDActive = true
  self.touchPad = false
  self.mainHUDPriorityList = priorityList.PriorityList.New(priorityList.STATES.UNSET)
  self.mainHUDPriorityList:AddItem("In Shell", function()
    if UI.GetInScreen(consts.SHELL) then
      return false
    end
    return nil
  end)
  self.mainHUDPriorityList:AddItem("PhotoMode")
  self.mainHUDPriorityList:AddItem("MainHUD Active", function()
    return not self.mainHUDActive or nil
  end)
  self.mainHUDPriorityList:AddItem("DesignerMessage Pause")
  self.mainHUDPriorityList:AddItem("Cinematic")
  self.mainHUDPriorityList:AddItem("Designer-Specified")
  self.compassUsesTimer = false
  self.compassTimer = nil
  self.compassTimerTurnOffDelay = 4
  self.compassAlpha = 0.6
  self.compassFadeTime = 0.5
  self.compassIsWithinMarkerRadius = false
  self.compassObj = util.GetUiObjByName("Compass")
  self.compassBase = util.GetUiObjByName("Compass_Base")
  self.compassRadius = util.GetUiObjByName("Compass_Radius")
  self.reticleForceState = hudConsts.FORCE_STATE_NONE
  self.reticleVisible = true
  self.reticlePriorityList = priorityList.PriorityList.New(priorityList.STATES.OFF)
  self.reticlePriorityList:Inherit(self.mainHUDPriorityList)
  self.reticlePriorityList:AddCounter("Action Force HUD State")
  self.reticlePriorityList:AddItem("Aim-Capable")
  self.reticlePriorityList:AddItem("Aiming")
  self.reticlePriorityList:AddItem("Rage Mode")
  self.reticlePriorityList:AddItemAtIndex(self.reticlePriorityList:GetIndexFromName("Cinematic"), "Minigame")
  self.goCombatHUD = util.GetUiObjByName("combatHUD")
  self.goHealthMeter = util.GetUiObjByName("HealthMeter")
  self.goRageMeter = util.GetUiObjByName("RageMeter")
  self.goSpecialMeters = util.GetUiObjByName("SpecialMeters")
  self.combatHUDFadeTime = 0.5
  self.combatHUDTurnOffDelay = 5
  self.combatHUDPriorityList = priorityList.PriorityList.New(priorityList.STATES.UNSET)
  self.combatHUDPriorityList:Inherit(self.mainHUDPriorityList)
  self.combatHUDPriorityList:AddCounter("Action Force HUD State")
  self.combatHUDPriorityList:AddItem("TouchPad", function()
    return self.touchPad and (not game.UI.GetUserCombatHUDSetting or game.UI.GetUserCombatHUDSetting() >= 2) or nil
  end)
  self.combatHUDPriorityList:AddItem("Aiming")
  self.combatHUDPriorityList:AddItem("In Combat", function()
    return game.Combat.GetCombatStatus() or nil
  end)
  self.combatHUDPriorityList:AddCounter("Near Consumable")
  self.combatHUDPriorityList:AddItem("Attacking")
  self.combatHUDPriorityList:AddCounter("Cooldown")
  self.combatHUDPriorityList:AddItem("Blocking")
  self.combatHUDPriorityList:AddItem("Low Health")
  self.combatHUDPriorityList:AddItemAtIndex(self.combatHUDPriorityList:GetIndexFromName("DesignerMessage Pause"), "HUD Display Setting", function()
    if game.UI.GetUserCombatHUDSetting ~= nil then
      local setting = game.UI.GetUserCombatHUDSetting()
      return self:HandleDisplaySetting(setting)
    end
    return nil
  end)
  self.combatHUDPriorityList:AddItemAtIndex(self.combatHUDPriorityList:GetIndexFromName("DesignerMessage Pause"), "Max Health/Rage Upgrade")
  self.goSonMeters = util.GetUiObjByName("SonMeters")
  self.goSonMetersBlur = util.GetUiObjByName("SonMetersBlur")
  self.goCornerHUD_Blur = util.GetUiObjByName("CornerHUD_Blur")
  self.sonHUDPriorityList = priorityList.PriorityList.New(priorityList.STATES.ON)
  self.sonHUDPriorityList:AddItem("HUD Display Setting", function()
    if game.UI.GetUserCombatHUDSetting ~= nil then
      local setting = game.UI.GetUserCombatHUDSetting()
      return self:HandleDisplaySetting(setting)
    end
    return nil
  end)
  self.sonHUDPriorityList:AddCounter("Action Force HUD State")
  self.sonHUDPriorityList:AddItem("Son Incapacitated")
  self.sonHUDPriorityList:AddItem("Available In Level", function()
    if util.SonUI_ShouldShow() then
      return nil
    end
    return false
  end)
  self.compassPriorityList = priorityList.PriorityList.New(priorityList.STATES.UNSET)
  self.compassPriorityList:AddItem("HUD Display Setting", function()
    if game.UI.GetUserCompassSetting ~= nil then
      local setting = game.UI.GetUserCompassSetting()
      return self:HandleDisplaySetting(setting)
    end
    return nil
  end)
  self.compassPriorityList:AddCounter("Action Force HUD State")
  self.compassPriorityList:AddItem("C++ Priority List", Compass.ShouldBeDisplayed)
  if game.GOLD_VERSION ~= 1 then
    self.VFS = {
      debugCombatHUD = engine.VFSBool.New("Debug Combat HUD Visibility"),
      debugReticle = engine.VFSBool.New("Debug Reticle Visibility"),
      debugSonHUD = engine.VFSBool.New("Debug Son HUD Visibility")
    }
    function self.Update()
      if self.VFS.debugReticle.value == true then
        self.reticlePriorityList:DrawDebugTable()
      elseif self.VFS.debugCombatHUD.value == true then
        self.combatHUDPriorityList:DrawDebugTable()
      elseif self.VFS.debugSonHUD.value == true then
        self.sonHUDPriorityList:DrawDebugTable()
      end
    end
  end
end
function MainHUD:SetRagePrompts()
  local pad = game.Player.FindPlayer().Pad
  if pad.IsKeyboardAndMouse then
    self.goRageMeter:SetMaterialSwap("key")
    if game.GetEnterRageModeOptionNumber ~= nil and game.GetEnterRageModeOptionNumber() == 1 then
      self.goRageMeter:SetMaterialSwap(game.GetKey(6))
      self.goRageMeter:SetMaterialSwap(game.GetKey(5) .. "2")
    else
      self.goRageMeter:SetMaterialSwap(game.GetKey(13))
      self.goRageMeter:SetMaterialSwap(game.GetKey(10) .. "2")
    end
  elseif pad.IsGeneric then
    self.goRageMeter:SetMaterialSwap("")
    self.goRageMeter:SetMaterialSwap("genA")
    self.goRageMeter:SetMaterialSwap("genB2")
  else
    self.goRageMeter:SetMaterialSwap("")
  end
end
function MainHUD:Enter()
  self:WantPadEvents(true)
  self:AlphaFadeCombatHUDParts(0, 0)
  util.Show("combatHUD", "HealthMeter", "RageMeter", "SpecialMeters", "SonMeters", "messageHUD")
  UI.AlphaFade("Compass", 0, 0)
  util.Show("Compass")
  UI.SetGOScreenEdge("Compass")
  self:SetRagePrompts()
end
function MainHUD:EVT_UPDATE_WINDOW_SIZE()
  UI.SetGOScreenEdge("Compass")
end
function MainHUD:EVT_RAGE_ACCESS_OPTIONS_CHANGED()
  self:SetRagePrompts()
end
function MainHUD:EVT_PAD_CHANGED()
  self:SetRagePrompts()
end
function MainHUD:UpdateHUD(useTurnOffDelay)
  if self.mainHUDActive == true then
    util.Show("mainHUD")
    self:UpdateCompass()
    self:UpdateReticle()
    self:UpdateCombatHUD(useTurnOffDelay)
  else
    util.Hide("mainHUD")
  end
end
function MainHUD:EVT_UPDATE_COMPASS()
  self:StartTimer("TimerToUpdateCompass", 0.1, function()
    self:UpdateCompass()
  end)
end
function MainHUD:ShowCompass()
  if not self.mainHUDActive then
    return
  end
  Compass.Show()
  if self.compassIsWithinMarkerRadius == true then
    UI.Anim(self.compassBase, consts.AS_Forward_NoReset, "default")
    UI.Anim(self.compassRadius, consts.AS_Forward_NoReset, "default")
    UI.Anim(self.compassObj, consts.AS_Forward_NoReset, "default")
    if game.Wallets.GetResourceValue("HERO", "CompassRadiusTutorial") < 0 then
      game.Wallets.AddResource("HERO", "CompassRadiusTutorial", 1, "NO_TELEMETRY")
      uiCalls.SendSplashScreenDesignerMessage({
        Text = 43234,
        Title = 43237,
        AdvanceType = uiCalls.msgParam.ADVANCE_PRESS,
        ImageMaterialName = "Compass_Radius"
      })
      UI.SoftSavePlayerState()
    end
  else
    UI.Anim(self.compassBase, consts.AS_Reverse_NoReset, "default")
    UI.Anim(self.compassRadius, consts.AS_Reverse_NoReset, "default")
    UI.Anim(self.compassObj, consts.AS_Reverse_NoReset, "default")
  end
  UI.AlphaFade("Compass", self.compassAlpha, self.compassFadeTime)
  if self.compassUsesTimer then
    self:StartTimer("TimerToTurnOffCompass", self.compassTimerTurnOffDelay, function()
      self:HideCompass()
    end)
  end
end
function MainHUD:HideCompass()
  if not self.mainHUDActive then
    return
  end
  if self.compassUsesTimer and self:HaveTimer("TimerToTurnOffCompass") then
    self:StopTimer("TimerToTurnOffCompass")
  end
  Compass.Hide()
  local fadeAmount = 0
  UI.AlphaFade("Compass", fadeAmount, self.compassFadeTime)
end
function MainHUD:UpdateCompass()
  if self.compassPriorityList:GetAvailable() then
    self:ShowCompass()
  else
    self:HideCompass()
  end
end
function MainHUD:GetMarkerType(isMainQuest)
  return isMainQuest == true and consts.COMPASS_MARKER_TYPE_MAIN or consts.COMPASS_MARKER_TYPE_SIDE
end
function MainHUD:ShowReticle()
  util.Show("reticle")
end
function MainHUD:HideReticle()
  util.Hide("reticle")
end
function MainHUD:UpdateReticle()
  if self.reticlePriorityList:GetAvailable() or game.GetReticleAlwaysOn() and not game.Cinematics.IsInCinematicMode() and not UI.GetInScreen(consts.SHELL) then
    self:ShowReticle()
  else
    self:HideReticle()
  end
end
function MainHUD:AlphaFadeKratosHUDParts(fadeAmount, fadeTime)
  UI.AlphaFade(self.goCombatHUD, fadeAmount, fadeTime)
  UI.AlphaFade(self.goHealthMeter, fadeAmount, fadeTime)
  UI.AlphaFade(self.goRageMeter, fadeAmount, fadeTime)
  UI.AlphaFade(self.goSpecialMeters, fadeAmount, fadeTime)
end
function MainHUD:AlphaFadeSonHUDParts(fadeAmount, fadeTime)
  UI.AlphaFade(self.goSonMeters, fadeAmount, fadeTime)
  UI.AlphaFade(self.goSonMetersBlur, fadeAmount, fadeTime)
  UI.AlphaFade(self.goCornerHUD_Blur, fadeAmount, fadeTime)
end
function MainHUD:AlphaFadeCombatHUDParts(fadeAmount, fadeTime)
  self:AlphaFadeKratosHUDParts(fadeAmount, fadeTime)
  self:AlphaFadeSonHUDParts(fadeAmount, fadeTime)
end
function MainHUD:ShowKratosHUD()
  if self:HaveTimer("TimerToTurnOffCombatHUD") then
    self:StopTimer("TimerToTurnOffCombatHUD")
  end
  self:AlphaFadeKratosHUDParts(1, self.combatHUDFadeTime)
end
function MainHUD:ShowSonHUD()
  if self:HaveTimer("TimerToTurnOffCombatHUD") then
    self:StopTimer("TimerToTurnOffCombatHUD")
  end
  self:AlphaFadeSonHUDParts(1, self.combatHUDFadeTime)
end
function MainHUD:HideCombatHUD(useTurnOffDelay)
  if useTurnOffDelay == true then
    self:StartTimer("TimerToTurnOffCombatHUD", self.combatHUDTurnOffDelay, function()
      self:TurnOffCombatHUD()
    end)
  else
    self:TurnOffCombatHUD()
  end
end
function MainHUD:TurnOffCombatHUD()
  self:AlphaFadeCombatHUDParts(0, self.combatHUDFadeTime)
end
function MainHUD:UpdateCombatHUD(useTurnOffDelay)
  local state = self.combatHUDPriorityList:GetAvailable()
  if state == true then
    self:ShowKratosHUD()
    if self.sonHUDPriorityList:GetAvailable() then
      self:ShowSonHUD()
    else
      self:AlphaFadeSonHUDParts(0, self.combatHUDFadeTime)
    end
  else
    self:HideCombatHUD(state == nil and useTurnOffDelay)
  end
  local player = game.Player.FindPlayer()
  if player:PickupIsAcquired("ForceRageModeDisabled") then
    UI.AlphaFade("RageMeter", 0, self.combatHUDFadeTime)
  end
end
function MainHUD:EVT_PlayHUDSound(soundName, isSonSound)
  if not hudConsts.SoundsRespectDisplayLevel or self.combatHUDPriorityList:GetAvailable() ~= false and (not isSonSound or self.sonHUDPriorityList:GetAvailable() ~= false) then
    game.Audio.PlaySound(soundName)
  end
end
function MainHUD:EVT_UpdateCombatStatus()
  self.reticleVisible = game.Combat.GetCombatStatus()
  self:UpdateHUD(true)
end
MainHUD.EVT_EnterCombat = MainHUD.EVT_UpdateCombatStatus
MainHUD.EVT_ExitCombat = MainHUD.EVT_UpdateCombatStatus
function MainHUD:EVT_TURN_MAIN_HUD_OFF()
  self.mainHUDActive = false
  self:UpdateHUD(false)
end
function MainHUD:EVT_TURN_MAIN_HUD_ON()
  self.mainHUDActive = true
  self:UpdateHUD(true)
end
function MainHUD:EVT_REFRESH_HUD()
  self:UpdateHUD(true)
end
function MainHUD:EVT_CINEMATIC_MODE_END()
  self.mainHUDPriorityList:SetItemByName("Cinematic", nil)
  self:UpdateHUD(true)
  self:UpdateReticle()
end
function MainHUD:EVT_CINEMATIC_MODE_START()
  self.mainHUDPriorityList:SetItemByName("Cinematic", false)
  self:UpdateHUD(false)
  self:UpdateReticle()
end
function MainHUD:EVT_COMPASS_TOGGLE_CHEAT()
  Compass.SetHaveCompass()
  Compass.SetDesignerForcedHide(false)
  self:UpdateCompass()
end
function MainHUD:EVT_ClearCompassMarkersForQuest(isMainQuest)
  local markerType = self:GetMarkerType(isMainQuest)
  Compass.HideAllMarkersOfType(markerType)
end
function MainHUD:EVT_ShowCompassMarkerForQuest(isMainQuest, markerNameHash)
  local markerType = self:GetMarkerType(isMainQuest)
  if not game.Compass.MultiCompassTargetQuestSupport then
    Compass.HideAllMarkersOfType(markerType)
  end
  Compass.ShowMarker(markerNameHash, markerType)
end
function MainHUD:EVT_HideCompassMarkerForQuest(isMainQuest, markerNameHash)
  Compass.HideMarker(markerNameHash)
end
function MainHUD:EVT_HandleWithinCompassMarkerRadius(markerNameHash, isWithinRadius)
  self.compassIsWithinMarkerRadius = isWithinRadius
  self:UpdateCompass()
end
function MainHUD:EVT_TURN_RAGE_METER_OFF()
  UI.AlphaFade("RageMeter", 0, self.combatHUDFadeTime)
end
function MainHUD:EVT_TURN_RAGE_METER_ON()
  UI.AlphaFade("RageMeter", 1, self.combatHUDFadeTime)
end
function MainHUD:EVT_AIM_END()
  self.combatHUDPriorityList:SetItemByName("Aiming", nil)
  self.reticlePriorityList:SetItemByName("Aiming", nil)
  self:UpdateCombatHUD(true)
  self:UpdateReticle()
end
function MainHUD:EVT_AIM_START()
  self.combatHUDPriorityList:SetItemByName("Aiming", true)
  self.reticlePriorityList:SetItemByName("Aiming", true)
  self:UpdateCombatHUD(true)
  self:UpdateReticle()
end
function MainHUD:EVT_AIM_CAPABLE(capable)
  self.reticlePriorityList:SetItemByName("Aim-Capable", capable)
  self:UpdateReticle()
end
function MainHUD:EVT_BLOCK_END()
  self.combatHUDPriorityList:SetItemByName("Blocking", nil)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_BLOCK_START()
  self.combatHUDPriorityList:SetItemByName("Blocking", true)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_ATTACK_END()
  self.combatHUDPriorityList:SetItemByName("Attacking", nil)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_ATTACK_START()
  self.combatHUDPriorityList:SetItemByName("Attacking", true)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_PlayerNearHealthRage(isNear)
  self.combatHUDPriorityList:SetItemByName("Near Consumable", isNear or nil)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_COOLDOWN_METER_END(pickupName)
  self.combatHUDPriorityList:SetItemByName("Cooldown", nil)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_COOLDOWN_METER_START(pickupName)
  local playerCreature = game.Player.FindPlayer()
  playerCreature:CallScript("LuaHook_CombatEvent_CooldownActivated", pickupName)
  self.combatHUDPriorityList:SetItemByName("Cooldown", true)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_PLAYTEST_MODE_END()
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_PLAYTEST_MODE_START()
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_LOW_HEALTH_END()
  self.combatHUDPriorityList:SetItemByName("Low Health", nil)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_LOW_HEALTH_START()
  self.combatHUDPriorityList:SetItemByName("Low Health", true)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_MAX_HEALTHRAGE()
  if game.UI.GetUserCombatHUDSetting and self:HandleDisplaySetting(game.UI.GetUserCombatHUDSetting) == false then
    return
  end
  self.combatHUDPriorityList:SetItemByName("Max Health/Rage Upgrade", true)
  self:UpdateCombatHUD(true)
  self:StartTimer("MaxHealthRageHelper", 5, function()
    self.combatHUDPriorityList:SetItemByName("Max Health/Rage Upgrade", nil)
    self:UpdateCombatHUD(false)
  end)
end
function MainHUD:EVT_DM_PAUSE()
  self.mainHUDPriorityList:SetItemByName("DesignerMessage Pause", false)
  self:UpdateCombatHUD(false)
end
function MainHUD:EVT_DM_UNPAUSE()
  self.mainHUDPriorityList:SetItemByName("DesignerMessage Pause", nil)
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_RAGE_START()
  self.reticlePriorityList:SetItemByName("Rage Mode", false)
  self:UpdateReticle()
end
function MainHUD:EVT_RAGE_END()
  self.reticlePriorityList:SetItemByName("Rage Mode", nil)
  self:UpdateReticle()
end
function MainHUD:EVT_MINIGAME_START()
  self.reticlePriorityList:SetItemByName("Minigame", true)
  self:UpdateReticle()
end
function MainHUD:EVT_MINIGAME_END()
  self.reticlePriorityList:SetItemByName("Minigame", nil)
  self:UpdateReticle()
end
function MainHUD:EVT_TEMP_ON(showSonHUD)
  if self:HandleDisplaySetting(game.UI.GetUserCombatHUDSetting()) == false then
    return
  end
  self:ShowKratosHUD()
  if showSonHUD and self.sonHUDPriorityList:GetAvailable() then
    self:ShowSonHUD()
  end
  self:UpdateCombatHUD(true)
end
function MainHUD:EVT_TEMP_OFF()
  self:HideCombatHUD(false)
  self:UpdateCombatHUD(false)
end
function MainHUD:EVT_COMBAT_HUD_STATE(newState)
  self.mainHUDPriorityList:SetItemByName("Designer-Specified", newState)
  self:UpdateHUD(true)
end
function MainHUD:EVT_SonGrabStart()
  self.sonHUDPriorityList:SetItemByName("Son Incapacitated", true)
end
function MainHUD:EVT_SonGrabEnd()
  self.sonHUDPriorityList:SetItemByName("Son Incapacitated", nil)
end
function MainHUD:EVT_TURN_PHOTO_MODE_ON()
  self.mainHUDPriorityList:SetItemByName("PhotoMode", false)
  self:UpdateHUD(true)
end
function MainHUD:EVT_TURN_PHOTO_MODE_OFF()
  self.mainHUDPriorityList:SetItemByName("PhotoMode", nil)
  self:UpdateHUD(true)
end
function MainHUD:EVT_tActionForceHUDState(argsTable)
  local newState, cbtHud, sonHUD, reticle, _, compass = unpack(argsTable)
  if cbtHud then
    self.combatHUDPriorityList:SetItemByName("Action Force HUD State", newState)
  end
  if sonHUD then
    self.sonHUDPriorityList:SetItemByName("Action Force HUD State", newState)
  end
  if reticle then
    self.reticlePriorityList:SetItemByName("Action Force HUD State", newState)
  end
  if compass then
    self.compassPriorityList:SetItemByName("Action Force HUD State", newState)
  end
  self:UpdateHUD(true)
end
function MainHUD:EVT_TOUCH_STARTED()
  self.touchPad = true
  _G.touchPad = true
  self:UpdateHUD(true)
end
function MainHUD:EVT_TOUCH_ENDED()
  self.touchPad = false
  _G.touchPad = false
  self:UpdateHUD(false)
end
function MainHUD:EVT_TouchPad_Release()
  if game.UI.GetUserCompassSetting and game.UI.GetUserCompassSetting() >= 2 then
    UI.AlphaFade("Compass", 0, 0)
  end
  if game.UI.GetUserCombatHUDSetting and 2 <= game.UI.GetUserCombatHUDSetting() then
    self:AlphaFadeKratosHUDParts(0, 0)
    self:AlphaFadeSonHUDParts(0, 0)
  end
end
function MainHUD:EVT_OnInteractStart(creature, go)
  if creature and creature.GetPlayer and creature:GetPlayer() then
    self:EVT_TEMP_OFF()
  end
end
MainHUD.EVT_PlayerDamaged = MainHUD.EVT_TEMP_ON
MainHUD.EVT_GAME_START = MainHUD.EVT_REFRESH_HUD
function MainHUD:OnSaveCheckpoint(tab)
end
function MainHUD:OnRestoreCheckpoint(tab)
end
