local classlib = require("core.class")
local tablex = require("core.tablex")
local fsm = require("ui.fsm")
local lamsConsts = require("ui.lamsConsts")
local logTimer = require("ui.logTimer")
local mapUtil = require("ui.mapUtil")
local pickupConsts = require("ui.pickupConsts")
local questUtil = require("ui.questUtil")
local resourceConsts = require("ui.resourceConsts")
local runeUtil = require("ui.runeUtil")
local resourceUtil = require("ui.resourceUtil")
local uiCalls = require("ui.uicalls")
local util = require("ui.util")
local consts = require("ui.consts")
local hudConsts = require("ui.hudConsts")
local logManager = require("ui.logManager")
local compassSequence = require("ui.compassSequence")
local itemCardSequence = require("ui.itemCardSequence")
local journalSequence = require("ui.journalSequence")
local questSequence = require("ui.questSequence")
local areaAnnounceSequence = require("ui.areaAnnounceSequence")
local questCompleteSequence = require("ui.questSequenceSpecialComplete")
local questStartSequence = require("ui.questSequenceSpecialStart")
local resourceSequence = require("ui.resourceSequence")
local Player = game.Player
local SubObject = game.SubObject
local UI = game.UI
local TextLog = classlib.Class("TextLog", fsm.UIState)
local TextOff = TextLog:StateClass("TextOff", fsm.UIState)
local TextOn = TextLog:StateClass("TextOn", fsm.UIState)
local vendorOpen = false
local textLog = TextLog.New("textLog", {TextOff, TextOn})
local TrophyCheck = function(resourceName)
  if resourceName == "MaxHealthUpgrade" and game.Wallets.GetResourceValue("HERO", "MaxHealthUpgrade") == 3 then
    game.UnlockTrophy(17)
  end
  if resourceName == "MaxRageUpgrade" and game.Wallets.GetResourceValue("HERO", "MaxRageUpgrade") == 3 then
    game.UnlockTrophy(18)
  end
end
function TextLog:Enter()
  self:WantPadEvents(true)
  self:Goto("TextOn")
end
TextLog.EVT_GAME_START = TextLog.Enter
TextLog.EVT_Restart = TextLog.Enter
function TextLog:EVT_VENDOR_MENU_OPEN()
  vendorOpen = true
end
function TextLog:EVT_VENDOR_MENU_CLOSED()
  vendorOpen = false
end
function TextOff:Enter()
end
function TextOff:Exit()
end
local logPriorities = {
  ItemCard = 1,
  Resources = 2,
  QuestSpecial = 3,
  AreaAnnounce = 4,
  Quest = 4,
  Journal = 4,
  QuestMarker = 5
}
local logTracks = {
  ItemCard = 1,
  Resources = 2,
  QuestSpecial = 3,
  AreaAnnounce = 6,
  Quest = 4,
  Journal = 4,
  QuestMarker = 5
}
function TextOn:Setup()
  self.buffLogTimer = logTimer.LogTimer.New(self, {
    Name = "BuffLogTimer",
    LogObjectName = "BuffLogTimer",
    MaxDisplayRowCount = 5,
    SenderGameObject = Player.FindPlayer():GetGameObject(),
    IncludeTags = {
      pickupConsts.TAG_PICKUP_BUFF,
      pickupConsts.TAG_PICKUP_BUFF_NOTIMER
    }
  })
  self.goBuffLog = util.GetUiObjByName("BuffLogTimer")
  self.goQuestLog = util.GetUiObjByName("QuestLog")
  self.goJournalLog = util.GetUiObjByName("JournalLog")
  self.goResourceLog = util.GetUiObjByName("ResourceLog")
  self.inCinematic = false
  self.buffLogTimerHideCounter = 0
  self:BuffLogTimerVis()
  self.logManager = logManager.LogManager.New(self)
  self.subLogManager = logManager.LogManager.New(self)
  self.logManager:Register("Compass", compassSequence.InitSequenceArgs, false, logTracks.QuestMarker)
  self.logManager:Register("AreaAnnounce", areaAnnounceSequence.InitSequenceArgs, false, logTracks.AreaAnnounce)
  self.logManager:Register("ItemCard", itemCardSequence.InitSequenceArgs, true, logTracks.ItemCard)
  self.logManager:Register("Quest", questSequence.InitSequenceArgs, false, logTracks.Quest)
  self.logManager:Register("QuestSpecialStart", questStartSequence.InitSequenceArgs, false, logTracks.QuestSpecial)
  self.logManager:Register("QuestSpecialComplete", questCompleteSequence.InitSequenceArgs, false, logTracks.QuestSpecial)
  self.logManager:Register("Journal", journalSequence.InitSequenceArgs, false, logTracks.Journal)
  self.logManager:Register("ResourcesDispatch", resourceSequence.Dispatch_InitSequenceArgs, true, logTracks.Resources)
  self.subLogManager:Register("Resources", resourceSequence.InitSequenceArgs, true, logTracks.Resources)
end
function TextOn:UpdateLogPositions()
  UI.SetGOScreenLeft(self.goBuffLog)
  UI.SetGOScreenLeft(self.goQuestLog)
  UI.SetGOScreenRight(self.goJournalLog)
  UI.SetGOScreenRight(self.goResourceLog)
end
function TextOn:Enter()
  self:UpdateLogPositions()
  self.buffLogTimer:Initialize()
  self.buffLogTimer:Activate()
  self.buffLogTimerHideCounter = 0
  local timeUntilResourcesLogsAreAllowed = 3
  self.resourceLogsAllowed = false
  self:StartTimer("ResourceLogInitializationTimer", timeUntilResourcesLogsAreAllowed, function()
    self.resourceLogsAllowed = true
  end)
end
function TextOn:EVT_UPDATE_WINDOW_SIZE()
  self:UpdateLogPositions()
end
function TextOn:Update()
  self.logManager:Update()
  self.subLogManager:Update()
end
function TextOn:Exit()
  self.buffLogTimer:Deactivate()
end
function TextOn:Clear()
  self.logManager:Clear()
  self.subLogManager:Clear()
end
function TextOn:EVT_Journal_Log_Pause()
  self.logManager._uiPaused = true
end
function TextOn:EVT_Journal_Log_Unpause()
  self.logManager._uiPaused = false
end
function SuppressLastQuestIncrement(questID)
  local shouldSuppress = false
  local progressInfo = questUtil.GetProgressInfo(questID)
  if progressInfo ~= nil then
    local progress = questUtil.GetProgressInfoProgress(progressInfo)
    local goal = questUtil.GetProgressInfoGoal(progressInfo)
    shouldSuppress = progress >= goal
    if questUtil.HasFlag(questID, "DismissFirstIncrement") then
      shouldSuppress = shouldSuppress or false
    end
  end
  return shouldSuppress
end
function FormatProgressAndGoalIntoBody(questID, bodyLams)
  if bodyLams == nil or bodyLams == 0 then
    return "LAMS ID " .. tostring(bodyLams) .. " Not Found"
  end
  local info = questUtil.GetProgressInfo(questID)
  if info ~= nil then
    if questUtil.HasFlag(questID, "DismissFirstIncrement") and info.Progress == 0 and game.QuestManager.GetQuestState(questID) == "Activate" then
      info.Progress = 1
      if questUtil.HasFlag(questID, "Artifacts") then
        local newSetStr = util.FormatLAMSString(37825)
        local setInfoStr = util.FormatLAMSString(bodyLams, info.Progress, info.Goal)
        return newSetStr .. "\n" .. setInfoStr
      end
    end
    return util.FormatLAMSString(bodyLams, info.Progress, info.Goal)
  else
    return util.GetLAMSMsg(bodyLams)
  end
end
function InternalAddQuestLogMessage(logManager, args)
  local messageType = args.MessageType
  if messageType == tweaks.tQuestUiMessage.eMessageType.kQMS_Default then
    if SuppressLastQuestIncrement(args.Quest) then
      return
    end
    args.BodyStr = FormatProgressAndGoalIntoBody(args.Quest, args.Body)
    local questStages = questSequence.CreateSequenceStages(args)
    logManager:QueueMessage("Quest", questStages, logPriorities.Quest)
  elseif messageType == tweaks.tQuestUiMessage.eMessageType.kQMS_StartSpecial then
    local questStages = questStartSequence.CreateSequenceStages(args)
    logManager:QueueMessage("QuestSpecialStart", questStages, logPriorities.QuestSpecial)
  elseif messageType == tweaks.tQuestUiMessage.eMessageType.kQMS_CompleteSpecial then
    local questStages = questCompleteSequence.CreateSequenceStages(args)
    logManager:QueueMessage("QuestSpecialComplete", questStages, logPriorities.QuestSpecial)
  elseif messageType == tweaks.tQuestUiMessage.eMessageType.kQMS_Journal or messageType == tweaks.tQuestUiMessage.eMessageType.kQMS_Journal_NoTracking then
    if game.UI.GetUserGameplayNotificationsSetting and not game.UI.GetUserGameplayNotificationsSetting() then
      return
    end
    if messageType ~= tweaks.tQuestUiMessage.eMessageType.kQMS_Journal_NoTracking and SuppressLastQuestIncrement(args.Quest) then
      return
    end
    if messageType ~= tweaks.tQuestUiMessage.eMessageType.kQMS_Journal_NoTracking then
      args.EventData = {
        args.Quest
      }
      args.Event = "EVT_GO_TO_QUEST"
    end
    args.BodyStr = FormatProgressAndGoalIntoBody(args.Quest, args.Body)
    args.Sound = "SND_UX_HUD_Updates_Journal"
    args.ShowText = "ShowJournal"
    local journalStages = journalSequence.CreateSequenceStages(args)
    logManager:QueueMessage("Journal", journalStages, logPriorities.Journal)
  end
end
function InternalAddJournalMessage(logManager, args)
  if game.UI.GetUserGameplayNotificationsSetting and not game.UI.GetUserGameplayNotificationsSetting() then
    return
  end
  if args.Data ~= nil then
    local resource = args.Data.Resource
    if resource ~= nil then
      if string.sub(resource, -9) == "_PostBoat" then
        resource = string.sub(resource, 1, string.len(resource) - 9)
      end
      args.EventData = {resource}
      args.Event = "EVT_GO_TO_JOURNAL"
      args.Sound = "SND_UX_HUD_Updates_Journal"
      args.ShowText = "ShowJournal"
    elseif args.Data.Mapmarker ~= nil then
      local marker = args.Data.Mapmarker
      local realmName = mapUtil.MapMarker_GetRealmName(marker)
      args.EventData = {realmName, marker}
      args.Event = "EVT_GO_TO_MAP"
      args.Sound = "SND_UX_HUD_Updates_Map"
      args.ShowText = "ShowMap"
    end
  else
    args.Sound = "SND_UX_HUD_Updates_Journal"
  end
  args.BodyStr = util.GetLAMSMsg(args.Body)
  local journalStages = journalSequence.CreateSequenceStages(args)
  logManager:QueueMessage("Journal", journalStages, logPriorities.Journal)
end
local DismissResourceMessageBySourceType = function(args)
  local result = false
  local source = args.Source
  if source and (source == "RestoreState" or source == "Lua:Purchase" or source == "Lua:Craft" or source == "Lua:ExchangeRune") then
    result = true
  end
  return result
end
local InternalAddResourceMessage = function(logManager, args)
  if args.Amount and args.Amount <= 0 then
    return
  end
  if UI.GetInScreen(consts.SHELL) or UI.GetInScreen(consts.BOOT) or UI.GetInScreen(consts.LOADINGSCR) or UI.GetInScreen(consts.DEADSCR) then
    return
  end
  local shouldUseItemCard = false
  if args.Id ~= nil then
    args.Amount = 1
    args.ResourceName = args.Id
    args.ResourceType = resourceConsts.RESOURCE_FLAG_RUNE
    shouldUseItemCard = runeUtil.ShouldUseItemCard(args.Id)
  elseif game.Resources.HasFlag(args.ResourceName, resourceConsts.RESOURCE_FLAG_PICKUP) then
    args.ResourceType = resourceConsts.RESOURCE_FLAG_PICKUP
    shouldUseItemCard = resourceUtil.ShouldUseItemCard(args.ResourceName, vendorOpen)
  else
    for i = 1, #resourceConsts.RESOURCE_LORE_CATEGORY_FLAGS do
      if resourceUtil.HasFlag(args.ResourceName, resourceConsts.RESOURCE_LORE_CATEGORY_FLAGS[i]) then
        InternalAddJournalMessage(logManager, {
          Header = lamsConsts.Lore_Added,
          Body = lamsConsts.New_Triptych_Entry,
          Icon = "Lore",
          Data = {
            Resource = args.ResourceName
          }
        })
        return
      end
    end
    args.ResourceType = resourceConsts.RESOURCE_FLAG_RESOURCE
    shouldUseItemCard = resourceUtil.ShouldUseItemCard(args.ResourceName, vendorOpen)
    TrophyCheck(args.ResourceName)
  end
  if vendorOpen then
    shouldUseItemCard = false
  end
  if shouldUseItemCard then
    if args.DebugAdd then
      return
    end
    local itemCardArgs = itemCardSequence.CreateItemCardArgs(args)
    logManager:QueueMessage("ItemCard", itemCardArgs, logPriorities.ItemCard)
  else
    local displaySetting = game.UI.GetUserHUDDisplaySetting()
    if game.UI.GetUserGameplayNotificationsSetting and not game.UI.GetUserGameplayNotificationsSetting() then
      return
    end
    if args.Id ~= nil then
      if runeUtil.HasFlag(args.Id, resourceConsts.RESOURCE_FLAG_DONOTDISPLAYRUNE) then
        return
      end
    elseif not game.Resources.HasFlag(args.ResourceName, resourceConsts.RESOURCE_FLAG_DISPLAY_UI) then
      return
    elseif DismissResourceMessageBySourceType(args) then
      return
    end
    local resourceStages = resourceSequence.Dispatch_CreateSequenceStages(args)
    logManager:QueueMessage("ResourcesDispatch", resourceStages, logPriorities.Resources)
  end
end
function TextOn:EVT_DeadMenu()
  self:Clear()
  self.logManager:SetDisableInputItemByName("DeadMenu", true)
  self.subLogManager:SetDisableInputItemByName("DeadMenu", true)
end
function TextOn:EVT_CLOSE_FAKE_DEATH_SCREEN()
  self.logManager:SetDisableInputItemByName("DeadMenu", nil)
  self.subLogManager:SetDisableInputItemByName("DeadMenu", nil)
end
function TextOn:EVT_GAME_START()
  self.logManager:ClearDisableInputItems()
  self.subLogManager:ClearDisableInputItems()
end
TextOn.EVT_GAME_OVER = TextOn.EVT_GAME_START
TextOn.EVT_Restart = TextOn.EVT_GAME_START
function TextOn:EVT_SEND_MSG_TO_RESOURCE_LOG(args)
  InternalAddResourceMessage(self.logManager, args)
end
function TextOn:EVT_HandleResourceAmountChange(args)
  InternalAddResourceMessage(self.logManager, args)
end
function TextOn:EVT_HandleRuneAdded(args)
  InternalAddResourceMessage(self.logManager, args)
end
function TextOn:AddResourceMessageToSubManager(args)
  self.subLogManager:QueueMessage("Resources", args, 1)
end
function TextOn:EVT_SEND_MSG_TO_QUEST_LOG(args)
  InternalAddQuestLogMessage(self.logManager, args)
end
function TextOn:EVT_QUEUE_DISCOVER_LOCATION(args)
  if game.UI.GetUserGameplayNotificationsSetting and not game.UI.GetUserGameplayNotificationsSetting() then
    mapUtil.Region_SetState(args.text, tweaks.eTokenState.kDiscovered)
    return
  end
  local areaAnnounceStages = areaAnnounceSequence.CreateSequenceStages(args)
  self.logManager:QueueMessage("AreaAnnounce", areaAnnounceStages, logPriorities.AreaAnnounce)
end
function TextOn:EVT_HandleQuestStateChange(args)
  InternalAddQuestLogMessage(self.logManager, args)
end
function TextOn:EVT_AllMainQuestAndSummariesCompleted()
  local args = {
    Is100Complete = true,
    Header = 44367,
    Body = 44278
  }
  local questStages = questCompleteSequence.CreateSequenceStages(args)
  self.logManager:QueueMessage("QuestSpecialComplete", questStages, logPriorities.QuestSpecial)
end
function TextOn:EVT_SEND_MSG_TO_JOURNAL_LOG(args)
  args.Header = lamsConsts[args.Header]
  args.Body = lamsConsts[args.Body]
  InternalAddJournalMessage(self.logManager, args)
end
function TextOn:EVT_HandleJournalStateChange(args)
  InternalAddJournalMessage(self.logManager, args)
end
function TextOn:EVT_QueueCompassMarkerForQuestEvent(args)
  local compassStages = compassSequence.CreateSequenceStages(args)
  self.logManager:QueueMessage("Compass", compassStages, logPriorities.QuestMarker)
end
function TextOn:EVT_GLOBAL_MENU_OPEN()
  self.logManager:SetDisableInputItemByName("GlobalMenu", true)
  self.subLogManager:SetDisableInputItemByName("GlobalMenu", true)
end
function TextOn:EVT_GLOBAL_MENU_CLOSED()
  self.logManager:SetDisableInputItemByName("GlobalMenu", nil)
  self.subLogManager:SetDisableInputItemByName("GlobalMenu", nil)
end
function TextOn:EVT_DM_PAUSE()
  self.logManager:SetDisableInputItemByName("DesignerMessages", true)
  self.subLogManager:SetDisableInputItemByName("DesignerMessages", true)
end
function TextOn:EVT_DM_UNPAUSE()
  self.logManager:SetDisableInputItemByName("DesignerMessages", nil)
  self.subLogManager:SetDisableInputItemByName("DesignerMessages", nil)
end
function TextOn:BuffLogTimerVis()
  local shouldHandle = game.UI.GetUserCombatHUDSetting() and util.HandleDisplaySetting(game.UI.GetUserCombatHUDSetting()) ~= false
  if self.buffLogTimerHideCounter < 0 or self.inCinematic or not shouldHandle then
    self.buffLogTimer:FadeOut()
  else
    self.buffLogTimer:FadeIn()
  end
end
function TextOn:EVT_tActionForceHUDState(argsTable)
  local newState, _, _, _, relevant, _ = unpack(argsTable)
  if relevant then
    if newState then
      self.buffLogTimerHideCounter = self.buffLogTimerHideCounter + 1
    else
      self.buffLogTimerHideCounter = self.buffLogTimerHideCounter - 1
    end
    self:BuffLogTimerVis()
  end
end
function TextOn:EVT_REFRESH_HUD()
  self:BuffLogTimerVis()
end
function TextOn:EVT_CINEMATIC_MODE_START()
  self.inCinematic = true
  self.logManager:BroadcastCinematicBegan()
  self:BuffLogTimerVis()
end
function TextOn:EVT_CINEMATIC_MODE_END()
  self.inCinematic = false
  self:BuffLogTimerVis()
end
function TextOn:EVT_TOUCH_STARTED()
  self:BuffLogTimerVis()
end
function TextOn:EVT_TOUCH_ENDED()
  self:BuffLogTimerVis()
end
function TextLog:OnSaveCheckpoint(tab)
end
function TextLog:OnRestoreCheckpoint(tab)
end
