local classlib = require("core.class")
local tablex = require("core.tablex")
local animationUtil = require("ui.animationUtil")
local buttonUtil = require("ui.buttonUtil")
local colors = require("ui.colors")
local consts = require("ui.consts")
local fsm = require("ui.fsm")
local lamsIDs = require("ui.lamsConsts")
local list = require("ui.list")
local mapUtil = require("ui.mapUtil")
local menu = require("ui.menu")
local pickupConsts = require("ui.pickupConsts")
local questConsts = require("ui.questConsts")
local questUtil = require("ui.questUtil")
local resourceConsts = require("ui.resourceConsts")
local resourceUtil = require("ui.resourceUtil")
local util = require("ui.util")
local tutorialUtil = require("ui.tutorialUtil")
local UI = game.UI
local QuestManager = game.QuestManager
local SetText = UI.SetText
local GetTextHandle = util.GetTextHandle
local Audio = game.Audio
local QuestsMenu = classlib.Class("QuestsMenu", fsm.UIState)
local QuestsOff = QuestsMenu:StateClass("QuestsOff", fsm.UIState)
local QuestsOn = QuestsMenu:StateClass("QuestsOn", fsm.UIState)
local MainQuests = QuestsMenu:StateClass("MainQuests", fsm.UIState)
local SideQuests = QuestsMenu:StateClass("SideQuests", fsm.UIState)
local Artifacts = QuestsMenu:StateClass("Artifacts", fsm.UIState)
local Labors = QuestsMenu:StateClass("Labors", fsm.UIState)
local TreasureMaps = QuestsMenu:StateClass("TreasureMaps", fsm.UIState)
local questsMenu = QuestsMenu.New("questsMenu", {
  QuestsOff,
  QuestsOn,
  {
    MainQuests,
    SideQuests,
    Artifacts,
    Labors,
    TreasureMaps
  }
})
function QuestsMenu:Setup()
  self.pauseMenuOpened = false
end
function QuestsMenu:Enter()
  self:WantPadEvents(true)
  self:TurnOff()
end
function QuestsMenu:TurnOff()
  self:Goto("QuestsOff")
end
function QuestsMenu:EVT_PAUSE_MENU_OPEN()
  self.pauseMenuOpened = true
end
QuestsMenu.EVT_GAME_OVER = QuestsMenu.TurnOff
QuestsMenu.EVT_Restart = QuestsMenu.TurnOff
function GetObjectiveInfo(activeChildQuestId)
  local questDesc = ""
  local rewardDesc = ""
  local rewardsHeader = ""
  local childTrackingInfo = questUtil.GetTrackingInfo(activeChildQuestId)
  local childQuestInfo = questUtil.CreateQuestInfo(activeChildQuestId, 0, childTrackingInfo)
  if childQuestInfo.ProgressInfo ~= nil then
    local progressInfo = childQuestInfo.ProgressInfo
    local descLamsId = QuestManager.GetQuestDescriptionLams(activeChildQuestId)
    local progress_text = util.FormatLAMSString(descLamsId, questUtil.GetProgressInfoProgress(progressInfo), questUtil.GetProgressInfoGoal(progressInfo))
    questDesc = progress_text
  else
    questDesc = questUtil.GetQuestDescriptionFromID(activeChildQuestId)
  end
  local rewardDescLamsId = QuestManager.GetQuestRewardLams(activeChildQuestId)
  if rewardDescLamsId == 0 and childTrackingInfo ~= nil then
    rewardDescLamsId = QuestManager.GetQuestRewardLams(questUtil.TrackingInfo_GetRootQuestID(childTrackingInfo))
  end
  if rewardDescLamsId ~= 0 then
    rewardDesc = util.GetLAMSMsg(rewardDescLamsId)
    if game.GetNewGamePlus() and questUtil.HasAnyFlagInTable(activeChildQuestId, {
      "MainQuest",
      "SideQuest_BrokSindri",
      "UnfinishedBusiness",
      "Dragon",
      "Valkyrie",
      "Artifacts",
      "Labor_World",
      "TreasureMap"
    }) then
      rewardDesc = rewardDesc .. "\n" .. util.GetLAMSMsg(lamsIDs.AdditionalNGPRewards)
    end
    rewardsHeader = util.GetLAMSMsg(lamsIDs.RewardsHeader)
  end
  return questDesc, rewardDesc, rewardsHeader
end
function QuestsOff:Setup()
  self.questsOn = self:GetState("QuestsOn")
end
function QuestsOff:Enter()
  util.Hide("sonJournal_Main")
end
function QuestsOff:Exit()
  util.Hide("sonJournal_Main")
end
function QuestsOff:EVT_TURN_ON_QUESTS_MENU(instructionEntries, instructionArgs)
  self.questsOn.menu:set_instructionEntries(instructionEntries)
  self.questsOn.menu:set_instructionArgs(instructionArgs)
  self:Goto("QuestsOn")
end
function QuestsOn:Setup()
  self.player = nil
  self.IsKeyboardAndMouse = false
  self.menu = menu.Menu.New(self, {})
  self.questsMenu = self:GetState("questsMenu")
  self.menu:SetupSubmenuList(consts.inworldMenu_SubmenuList, nil, nil)
  self.goSonJournal_Main = util.GetUiObjByName("sonJournal_Main")
  self.goJournalLightGroup = util.GetUiObjByName("JournalLight_Grp")
  self.goQuests_Group = util.GetUiObjByName("Quests_Group")
  self.goQuestInfo = self.goQuests_Group:FindSingleGOByName("QuestInfo")
  self.goQuestIcon = self.goQuestInfo:FindSingleGOByName("QuestIcon")
  self.goTrackQuest_Group = self.goQuestInfo:FindSingleGOByName("TrackQuest_Group")
  local thGoToMap = GetTextHandle(self.goTrackQuest_Group, "GoToMap")
  UI.SetTextIsClickable(thGoToMap)
  SetText(thGoToMap, "[SquareButton] " .. util.GetLAMSMsg(lamsIDs.GoToMap))
  self.thTrackQuest = GetTextHandle(self.goTrackQuest_Group, "TrackQuest")
  UI.SetTextIsClickable(self.thTrackQuest)
  self.thQuestRewardsHeader = util.GetTextHandle(self.goQuestInfo, "RewardsHeader")
  self.thQuestRewardDesc = util.GetTextHandle(self.goQuestInfo, "QuestRewardDesc")
  self.thQuestTitle = util.GetTextHandle(self.goQuestInfo, "QuestTitle")
  self.thQuestProgress = util.GetTextHandle(self.goQuestInfo, "QuestProgress")
  self.thQuestDesc = util.GetTextHandle(self.goQuestInfo, "QuestDesc")
  self.thQuestParentDesc = util.GetTextHandle(self.goQuestInfo, "QuestParentDesc")
  UI.Anim(self.goSonJournal_Main, consts.AS_Forward, "pageTurn03", 0, 1)
  self.goSonJournal_Main:Hide()
  self.goJournalLightGroup:Hide()
end
function QuestsOn:UpdateAccessibilityScaling()
  if UI.GetAccessibilityScaling == nil then
    return
  end
  self.goSonJournal_Main:SetLocalPosition(engine.Vector.New(-2.156 + UI.GetAccessibilityScaling(0, 0.05), 1.29, 6.41))
  self.goSonJournal_Main:SetScale(UI.GetAccessibilityScaling(5.87, 6.5))
  self.goQuests_Group:SetLocalPosition(engine.Vector.New(4.217 + UI.GetAccessibilityScaling(0, -0.55), 6.25 + UI.GetAccessibilityScaling(0, 1), 0))
  self.goQuests_Group:SetScale(UI.GetAccessibilityScaling(1, 1.15))
end
function QuestsOn:Update()
  local IsKeyboardAndMouse = self.player.Pad.IsKeyboardAndMouse
  if self.IsKeyboardAndMouse ~= IsKeyboardAndMouse then
    self.IsKeyboardAndMouse = IsKeyboardAndMouse
    self:UpdateFooterButtonPrompt(self:GetCurrentState().menu)
  end
end
function QuestsOn:Enter()
  self.player = game.Player.FindPlayer()
  self.IsKeyboardAndMouse = self.player.Pad.IsKeyboardAndMouse
  self.menu:Activate()
  util.Show("Journal")
  self.goSonJournal_Main:Show()
  self.goJournalLightGroup:Show()
  local submenuList = self.menu:GetList(consts.inworldMenu_SubmenuList)
  if self.questsMenu.pauseMenuOpened == true then
    local init_useOnGainFocus = false
    submenuList:SetSelectedButton(1, init_useOnGainFocus)
    self.questsMenu.pauseMenuOpened = false
  end
  local newItemArray = self:GetSubStateNames()
  local showList = true
  local useOnGainFocus = not self.menu:HasInstructionEntryForMenuState()
  local itemDetermineFocusabilityFunc, getDisplayNameFunc
  self.menu:RefreshSubmenuList(submenuList, newItemArray, showList, useOnGainFocus, itemDetermineFocusabilityFunc, getDisplayNameFunc)
  local instant = true
  animationUtil.ResetCamera(pickupConsts.TAG_PICKUP_KRATOS, instant)
  animationUtil.MoveWorldUIMainList("ListJoint_Journal")
  self.menu:ExecuteInstructions()
end
function QuestsOn:Exit()
  self.menu:Deactivate(true)
  self.goSonJournal_Main:Hide()
  self.goJournalLightGroup:Hide()
  self.goQuests_Group:Hide()
  self.goQuestInfo:Hide()
  self.goQuestIcon:Hide()
end
function QuestsOn:GetSubStateNames()
  return consts.SUB_STATES.Quests
end
local QuestCategory = function(questId, currCategory)
  for _, category in ipairs(questConsts.QUEST_INCLUDE_FLAGS[currCategory]) do
    if QuestManager.QuestHasFlag(questId, category) then
      return category
    end
  end
  return nil
end
function QuestsOn:UpdateQuestsList(questList, currCategory, forceSetSelectedToLast)
  assert(questList ~= nil, "Quest list inside of journalMenu.lua was nil, this should never occur")
  local questInfoTable_displayQuests = {}
  local category_quests = {}
  for _, category in ipairs(questConsts.QUEST_INCLUDE_FLAGS[currCategory]) do
    category_quests[category] = {}
  end
  category_quests[questConsts.QUEST_STATE_COMPLETE] = {}
  local rootQuests = QuestManager.GetActiveRootQuestIds()
  for _, questId in ipairs(QuestManager.GetActiveRootQuestIds()) do
    local state = QuestManager.GetQuestState(questId)
    local trackingInfo = questUtil.GetTrackingInfo(questId)
    local questInfo = questUtil.CreateQuestInfo(questId, 0, trackingInfo)
    local category
    for _, categoryFlag in ipairs(questConsts.QUEST_INCLUDE_FLAGS[currCategory]) do
      if QuestManager.QuestHasFlag(questId, categoryFlag) then
        category = categoryFlag
        break
      end
    end
    if category ~= nil then
      if state == questConsts.QUEST_STATE_ACTIVE then
        tablex.FastInsert(category_quests[category], questInfo, #category_quests[category] + 1)
      elseif state == questConsts.QUEST_STATE_COMPLETE then
        tablex.FastInsert(category_quests[questConsts.QUEST_STATE_COMPLETE], questInfo, #category_quests[questConsts.QUEST_STATE_COMPLETE] + 1)
      end
    end
  end
  table.sort(category_quests[questConsts.QUEST_STATE_COMPLETE], function(a, b)
    return QuestManager.GetCompletionIndex(a.QuestID) > QuestManager.GetCompletionIndex(b.QuestID)
  end)
  local AddCategory = function(category)
    local quests = category_quests[category]
    if 0 < #quests then
      if not questConsts.QUEST_SKIP_CATEGORY_HEADER[category] then
        local categoryLamsId = lamsIDs[tostring(currCategory) .. "_" .. category] or lamsIDs[category]
        local categoryInfo = {
          Title = util.GetLAMSMsg(categoryLamsId),
          ButtonType = "category"
        }
        tablex.FastInsert(questInfoTable_displayQuests, categoryInfo, #questInfoTable_displayQuests + 1)
      end
      for i = 1, #quests do
        local questInfo = quests[i]
        questInfo.ButtonType = "button"
        tablex.FastInsert(questInfoTable_displayQuests, questInfo, #questInfoTable_displayQuests + 1)
      end
    end
  end
  for _, category in ipairs(questConsts.QUEST_INCLUDE_FLAGS[currCategory]) do
    AddCategory(category)
  end
  AddCategory(questConsts.QUEST_STATE_COMPLETE)
  local showList = true
  local useOnGainFocus = true
  local itemDetermineFocusabilityFunc = function(questInfo)
    if questInfo.ButtonType == "category" then
      return false
    end
    return true
  end
  local itemGetTextFunc = function(questInfo)
    if questInfo.ButtonType == "category" then
      return questInfo.Title
    else
      local indentedTitle = questUtil.GetQuestInfoTitle(questInfo)
      if questUtil.GetQuestInfoLevel(questInfo) > 0 then
        indentedTitle = consts.Footer_Spacer .. indentedTitle
      end
      return indentedTitle
    end
  end
  questList:Refresh(questInfoTable_displayQuests, showList, useOnGainFocus, itemDetermineFocusabilityFunc, itemGetTextFunc)
  if forceSetSelectedToLast == true then
    for index, questTable in ipairs(questList:GetItems()) do
      if questTable.State == questConsts.QUEST_STATE_ACTIVE then
        questList:SetSelectedButton(index, true)
      end
    end
  end
end
function QuestsOn:UpdateQuestInfo(currState, questInfo)
  self:UpdateFooterButtonPrompt(currState.menu)
  if questInfo == nil or not questUtil.IsValidID(questUtil.GetQuestInfoQuestID(questInfo)) then
    self.goQuests_Group:Hide()
    self.goQuestInfo:Hide()
    self.goQuestIcon:Hide()
    return
  end
  local questID = questUtil.GetQuestInfoQuestID(questInfo)
  local subQuestsList = currState.menu:GetList("subQuestsList")
  self.goQuests_Group:Show()
  self.goQuestInfo:Show()
  local questIcon = questUtil.GetQuestIcon(questID)
  self.goQuestIcon:Show()
  self.goQuestIcon:SetMaterialSwap(questIcon)
  UI.SetText(self.thQuestTitle, questUtil.GetQuestInfoTitle(questInfo))
  UI.SetText(self.thQuestParentDesc, questInfo.Desc)
  local activeChildQuestId = questUtil.GetFocusQuestStepFromParent(questInfo.QuestID)
  if activeChildQuestId ~= nil then
    self:UpdateObjectiveInfo(activeChildQuestId)
  end
  if questUtil.QuestIsComplete(questInfo) then
    subQuestsList:SetHeaderText(util.GetLAMSMsg(lamsIDs.Completed))
    UI.SetText(self.thQuestProgress, "")
  else
    subQuestsList:SetHeaderText(util.GetLAMSMsg(lamsIDs.Objectives))
  end
  self:UpdateTrackingInfo(questInfo)
  local questProgressText = questUtil.GetQuestInfoProgressInfoText(questInfo)
  UI.SetText(self.thQuestProgress, questProgressText)
  local questFilter = questUtil.CreateQuestFilter(questUtil.GetStatesByCategory(currState.category), {}, questUtil.GetFlagsByCategory(currState.category), {})
  local childQuestFilter = questUtil.CreateChildQuestFilter(questFilter)
  local childQuests = {}
  local childQuests_fixed = {}
  questUtil.AddQuestChildren(childQuests, questID, childQuestFilter)
  for _, quest_info in ipairs(childQuests) do
    local curQuestID = questUtil.GetQuestInfoQuestID(quest_info)
    local curQuestLams = QuestManager.GetQuestTitleLams(curQuestID)
    if curQuestID ~= questID and curQuestLams ~= 0 then
      quest_info.Checked = questUtil.QuestIsComplete(quest_info)
      tablex.FastInsert(childQuests_fixed, quest_info, #childQuests_fixed + 1)
    end
  end
  tablex.Reverse(childQuests_fixed)
  local subQuestIndex = 1
  if currState.category == questConsts.QUEST_CATEGORY_LABORS then
    for i, childQuestInfo in ipairs(childQuests_fixed) do
      subQuestIndex = i
      if not questUtil.QuestIsComplete(childQuestInfo) then
        break
      end
    end
  end
  local newItemArray = childQuests_fixed
  local showList = true
  local useOnGainFocus = true
  local itemDetermineFocusabilityFunc = function(questInfo)
    return true
  end
  local itemGetTextFunc = function(questInfo)
    return questUtil.GetQuestInfoTitle(questInfo)
  end
  subQuestsList:SetSelectedButton(subQuestIndex, true)
  subQuestsList:Refresh(newItemArray, showList, useOnGainFocus, itemDetermineFocusabilityFunc, itemGetTextFunc)
  subQuestsList:SetSelectedButton(subQuestIndex, true)
  self:UpdateFooterButtonPrompt(currState.menu)
end
function QuestsOn:UpdateObjectiveInfo(activeChildQuestId)
  local questDesc, rewardDesc, rewardsHeader = GetObjectiveInfo(activeChildQuestId)
  UI.SetText(self.thQuestDesc, questDesc)
  UI.SetText(self.thQuestRewardDesc, rewardDesc)
  UI.SetText(self.thQuestRewardsHeader, rewardsHeader)
end
function QuestsOn:UpdateTrackingText(trackingState)
  local trackingText = ""
  if trackingState == questConsts.TRACKING_STATE_TRACKED then
    trackingText = "[AdvanceButton] " .. util.GetLAMSMsg(lamsIDs.Untrack)
  elseif trackingState == questConsts.TRACKING_STATE_NOT_TRACKED then
    trackingText = "[AdvanceButton] " .. util.GetLAMSMsg(lamsIDs.Track)
  end
  SetText(self.thTrackQuest, trackingText)
end
function QuestsOn:UpdateTrackingInfo(questInfo)
  local questID = questUtil.GetQuestInfoQuestID(questInfo)
  if (questUtil.IsMainQuest(questID) or questUtil.IsTrackableSideQuest(questID)) and not questUtil.QuestIsComplete(questInfo) then
    self.goTrackQuest_Group:Show()
    if questUtil.IsMainQuest(questID) then
      self:UpdateTrackingText()
    else
      local trackingState = questUtil.GetQuestInfoGetTrackingState(questInfo)
      self:UpdateTrackingText(trackingState)
    end
  else
    self.goTrackQuest_Group:Hide()
  end
end
function QuestsOn:UpdateFooterButtonPrompt(currMenu)
  local questsList = currMenu:GetList("MainList")
  local currQuestInfo = questsList:GetSelectedItem()
  local showTouchPadMap = game.IsMapAvailable() and game.build.GOLD_VERSION ~= 0
  local showObjectives = not self.IsKeyboardAndMouse
  currMenu:UpdateFooterButton("Objectives", showObjectives)
  currMenu:UpdateFooterButton("Map", showTouchPadMap)
  currMenu:UpdateFooterButton("Weapon", true)
  currMenu:UpdateFooterButton("Skill", true)
  currMenu:UpdateFooterButton("Settings", true)
  currMenu:UpdateFooterButton("Exit", true)
  currMenu:UpdateFooterButtonText()
end
function QuestsOn:SubmenuList_Button_Update(button)
  local alphaValue = 1
  local fadeTime = 0
  button:AlphaFade(alphaValue, fadeTime)
  button:SetIcon(button:get_item())
  button:UpdateNewIcon(nil)
end
function QuestsOn:SubmenuList_Button_OnGainFocus(button)
  local currentItem = button:get_item()
  local subState = self:GetState(currentItem)
  local mainList = subState.menu:GetList("MainList")
  self.menu:SetSubmenuListLabelText(consts.inworldMenu_SubmenuList, "")
  mainList:SetHeaderText(util.GetLAMSMsg(lamsIDs[currentItem]))
  subState.menu:set_instructionEntries(self.menu:get_instructionEntries())
  self:Goto(currentItem)
end
function QuestsOn:SubmenuList_AfterDelay(list, delayStartButtonIndex, currButtonIndex)
end
function QuestsOn:MainList_Button_Update(button)
  assert(button ~= nil, "Attempted to call MainList_Button_Update without a Button!")
  local disableAlpha = 0.45
  local fadeTime = 0
  local questInfo = button:get_item()
  buttonUtil.UpdateColorQuad(button, nil)
  if button._buttonType ~= "button" then
    button:AlphaFade(1, 0)
    buttonUtil.UpdateTrackingIcon(button, false, false)
    return
  end
  if questInfo == nil then
    button:AlphaFade(disableAlpha, fadeTime)
    buttonUtil.UpdateTrackingIcon(button, false, false)
  else
    local questState = questUtil.GetQuestInfoState(questInfo)
    local trackingState = questUtil.GetQuestInfoGetTrackingState(questInfo)
    local questColor = questUtil.GetQuestInfoColor(questInfo)
    local fadeAlpha = questState == questConsts.QUEST_STATE_ACTIVE and 1 or disableAlpha
    local isTracked = trackingState == questConsts.TRACKING_STATE_TRACKED
    local questID = questUtil.GetQuestInfoQuestID(questInfo)
    local isMainQuest = questUtil.IsMainQuest(questID)
    button:AlphaFade(fadeAlpha, fadeTime)
    button:SetTextColor(questColor)
    buttonUtil.UpdateTrackingIcon(button, isMainQuest, isTracked)
  end
end
function QuestsOn:MainList_Button_OnGainFocus(currState, button)
  local questInfo = button:get_item()
  currState:UpdateQuestInfo(questInfo)
end
function QuestsOn:MainList_Button_ItemCompare(questInfo, otherQuestInfo)
  local otherQuestID = questUtil.GetQuestInfoQuestID(otherQuestInfo)
  return questUtil.QuestInfo_HasQuestID(questInfo, otherQuestID)
end
function QuestsOn:SubmenuSetup(currState)
  currState.menu = menu.Menu.New(currState, {
    FooterButtonInfo = {
      {
        Item = "Objectives",
        Text = "[JoystickR] " .. util.GetLAMSMsg(lamsIDs.Objectives)
      },
      {
        Item = "Map",
        Text = "[TouchPad] " .. util.GetLAMSMsg(lamsIDs.Map),
        EventHandlers = {
          {
            Events = {
              "EVT_TouchPad_Release"
            },
            Handler = function()
              self:SendEventToUIFsm("globalMenu", "EVT_GO_TO_MAP")
            end
          }
        }
      },
      {
        Item = "Weapon",
        Text = "",
        EventHandlers = {
          {
            Events = {
              "EVT_GO_TO_WEAPON_MENU"
            },
            Handler = function()
              self:SendEventToUIFsm("globalMenu", "EVT_GO_TO_WEAPON")
            end
          }
        }
      },
      {
        Item = "Skill",
        Text = "",
        EventHandlers = {
          {
            Events = {
              "EVT_GO_TO_SKILL_TREE_MENU"
            },
            Handler = function()
              self:SendEventToUIFsm("globalMenu", "EVT_GO_TO_SKILL_TREE")
            end
          }
        }
      },
      {
        Item = "Settings",
        Text = "[TriangleButton] " .. util.GetLAMSMsg(lamsIDs.Options),
        EventHandlers = {
          {
            Events = {
              "EVT_Triangle_Release"
            },
            Handler = function()
              self:Menu_Triangle_ReleaseHandler()
            end
          }
        }
      },
      {
        Item = "Exit",
        Text = "[BackButton] " .. util.GetLAMSMsg(lamsIDs.Exit),
        EventHandlers = {
          {
            Events = {
              "EVT_Back_Release",
              "EVT_Options_Release",
              "EVT_GO_TO_QUEST_MENU"
            },
            Handler = function()
              self:Menu_Back_ReleaseHandler()
            end
          }
        }
      }
    }
  })
  local questsList = list.List.New(currState, {
    MaxFocusableObjectCount = 10,
    ListObjectName = "PickupList",
    EventHandlers = {
      {
        Events = {
          "EVT_Advance_Release"
        },
        Handler = function()
          self:Quests_Quest_AdvanceReleaseHandler(currState)
        end
      }
    },
    HoverToSelect = true,
    DelayTime = 0.33,
    AfterDelay = function(list, delayStartButtonIndex, currButtonIndex)
    end,
    Button_Update = function(button)
      self:MainList_Button_Update(button)
    end,
    Button_OnGainFocus = function(button)
      self:MainList_Button_OnGainFocus(currState, button)
    end,
    Button_ItemCompare = function(item, otherItem)
      return self:MainList_Button_ItemCompare(item, otherItem)
    end
  })
  questsList:SetSelectedButton(1, false)
  currState.menu:SetList("MainList", questsList)
  local subQuestsList = list.List.New(currState, {
    MaxFocusableObjectCount = 7,
    ListObjectName = "SubQuestList",
    EmptyTextLamsID = lamsIDs.NoQuestsAvailable,
    PreviousEvents = {
      "EVT_RightStick_Up"
    },
    NextEvents = {
      "EVT_RightStick_Down"
    },
    HoverToSelect = true,
    Button_Update = function(button)
      button:UpdateCheckmark()
      button:SetTextColor(colors.BLACK, "small_text")
    end,
    Button_OnGainFocus = function(button)
      local item = button:get_item()
      if item ~= nil then
        self:UpdateObjectiveInfo(item.QuestID)
        button:SetTextColor(colors.WHITE, "small_text")
      end
    end,
    Button_OnLoseFocus = function(button)
      button:SetTextColor(colors.BLACK, "small_text")
    end
  })
  subQuestsList:SetSelectedButton(1, false)
  subQuestsList:SetHeaderText(util.GetLAMSMsg(lamsIDs.Objectives))
  currState.menu:SetList("subQuestsList", subQuestsList)
end
function QuestsOn:SubmenuEnter(currState, category)
  currState.menu:Activate()
  currState.category = category
  self.currState = currState
  UI.WorldUIRender("JournalMenuCamera")
  local questsList = currState.menu:GetList("MainList")
  self:UpdateQuestsList(questsList, category, false)
  local currentQuest = questsList:GetSelectedItem()
  currState:UpdateQuestInfo(currentQuest)
  currState.menu:ExecuteInstructions()
end
function QuestsOn:SubmenuExit(currState)
  currState.menu:Deactivate(true)
end
function QuestsOn:Menu_Back_ReleaseHandler()
  self:SendEventToUIFsm("globalMenu", "EVT_TURN_OFF_GLOBAL_MENU")
end
function QuestsOn:Menu_Triangle_ReleaseHandler()
  self:SendEventToUIFsm("globalMenu", "EVT_OPEN_SETTINGS_MENU")
end
function QuestsOn:Quests_Quest_AdvanceReleaseHandler(currState)
  if currState.name == "TreasureMaps" or currState.name == "Labors" or currState.name == "Artifacts" then
    return
  end
  local questsList = currState.menu:GetList("MainList")
  local currQuestInfo = questsList:GetSelectedItem()
  local stateChanged = false
  local playFlourish = false
  if currQuestInfo ~= nil then
    local questID = questUtil.GetQuestInfoQuestID(currQuestInfo)
    if questUtil.IsValidID(questID) then
      local isComplete = questUtil.QuestIsComplete(currQuestInfo)
      local isTrackableSideQuest = questUtil.IsTrackableSideQuest(questID)
      if not isComplete and isTrackableSideQuest then
        local trackingState = questUtil.GetQuestInfoGetTrackingState(currQuestInfo)
        if trackingState == questConsts.TRACKING_STATE_TRACKED then
          questUtil.UntrackSideQuest(questID)
          Audio.PlaySound("SND_UX_Pause_Menu_Map_RemoveFromCompass")
          stateChanged = true
        elseif trackingState == questConsts.TRACKING_STATE_NOT_TRACKED then
          questUtil.TrackSideQuest(questID)
          Audio.PlaySound("SND_UX_Pause_Menu_Map_AddToCompass")
          stateChanged = true
          playFlourish = true
        end
      end
    end
  end
  if stateChanged then
    self:UpdateQuestsList(questsList, currState.category, false)
    currQuestInfo = questsList:GetSelectedItem()
    self:UpdateTrackingInfo(currQuestInfo)
    if playFlourish then
      local currButton = questsList:GetSelectedButton()
      buttonUtil.TrackingIcon_AnimFlourish(currButton)
    end
  end
end
function QuestsOn:EVT_Square_Release()
  if not tutorialUtil.AreEventsAllowed({
    "EVT_Square_Release"
  }) then
    return true
  end
  self:Quests_Quest_SquareReleaseHandler(self.currState)
end
function QuestsOn:Quests_Quest_SquareReleaseHandler(currState)
  local questsList = currState.menu:GetList("MainList")
  local currQuestInfo = questsList:GetSelectedItem()
  if currQuestInfo ~= nil then
    local questID = questUtil.GetQuestInfoQuestID(currQuestInfo)
    if questUtil.IsValidID(questID) then
      local isComplete = questUtil.QuestIsComplete(currQuestInfo)
      if not isComplete then
        local trackingInfo = questUtil.GetTrackingInfo(questID)
        if questUtil.TrackingInfo_IsValid(trackingInfo) then
          local markers = questUtil.TrackingInfo_GetMarkers(trackingInfo, questID)
          local selectedMarker, realmName
          if markers ~= nil then
            selectedMarker = markers[1]
            realmName = mapUtil.MapMarker_GetRealmName(selectedMarker)
          end
          if not util.IsStringNilOrEmpty(realmName) and not util.IsStringNilOrEmpty(selectedMarker) then
            self:SendEventToUIFsm("globalMenu", "EVT_GO_TO_MAP", realmName, selectedMarker)
            Audio.PlaySound("SND_UX_Pause_Menu_Map_Jump_To_Map")
          elseif currState.name == "MainQuests" then
            self:SendEventToUIFsm("globalMenu", "EVT_GO_TO_MAP", mapUtil.GetPlayerRealm())
            Audio.PlaySound("SND_UX_Pause_Menu_Map_Jump_To_Map")
          end
        end
      end
    end
  end
end
function QuestsOn:Quests_BackReleaseHandler()
  util.Hide("QuestInfo")
  local questsList = self.menu:GetList("quests")
  local hideList = true
  local clearButtons = false
  questsList:Deactivate(hideList, clearButtons)
end
function QuestsOn:EVT_TURN_OFF_QUESTS_MENU()
  self:Goto("QuestsOff")
end
function MainQuests:Setup()
  self.questsOn = self:GetState("QuestsOn")
  self.questsOn:SubmenuSetup(self)
end
function MainQuests:Enter()
  self.questsOn:SubmenuEnter(self, questConsts.QUEST_CATEGORY_MAIN)
  self.questsOn:UpdateAccessibilityScaling()
end
function MainQuests:Exit()
  self.questsOn:SubmenuExit(self)
  self.questsOn.goQuests_Group:Hide()
  self.questsOn.goQuestInfo:Hide()
end
function MainQuests:UpdateQuestInfo(questInfo)
  self.questsOn:UpdateQuestInfo(self, questInfo)
end
function MainQuests:UpdateFooterButtonPrompt()
  self.questsOn:UpdateFooterButtonPrompt(self.menu)
end
function SideQuests:Setup()
  self.questsOn = self:GetState("QuestsOn")
  self.questsOn:SubmenuSetup(self)
end
function SideQuests:Enter()
  self.questsOn:SubmenuEnter(self, questConsts.QUEST_CATEGORY_SIDE)
  self.questsOn:UpdateAccessibilityScaling()
end
function SideQuests:Exit()
  self.questsOn:SubmenuExit(self)
  self.questsOn.goQuests_Group:Hide()
  self.questsOn.goQuestInfo:Hide()
end
function SideQuests:UpdateQuestInfo(questInfo)
  self.questsOn:UpdateQuestInfo(self, questInfo)
end
function SideQuests:UpdateFooterButtonPrompt()
  self.questsOn:UpdateFooterButtonPrompt(self.menu)
end
function Artifacts:Setup()
  self.questsOn = self:GetState("QuestsOn")
  self.questsOn:SubmenuSetup(self)
  self.goArtifacts = util.GetUiObjByName("Artifact_Group")
  self.goArtifactsDecal = util.GetUiObjByName("journal_ArtifactDecals"):FindSingleGOByName("root")
  self.artifactDecals = {
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true,
    true
  }
  for i = 1, 12 do
    self.artifactDecals[i] = self.goArtifactsDecal:FindSingleGOByName("artifactDecal" .. tostring(i))
  end
  self.thArtifactsTitle = util.GetTextHandle(self.goArtifacts, "QuestTitle1")
  self.thArtifactsDesc = util.GetTextHandle(self.goArtifacts, "QuestDesc1")
  self.thArtifactsRewardDesc = util.GetTextHandle(self.goArtifacts, "QuestRewardDesc1")
  local artifactsRewardsHeader = util.GetTextHandle(self.goArtifacts, "RewardsHeader1")
  UI.SetText(artifactsRewardsHeader, util.GetLAMSMsg(lamsIDs.RewardsHeader))
end
function Artifacts:UpdateAccessibilityScaling()
  if UI.GetAccessibilityScaling == nil then
    return
  end
  self.questsOn:UpdateAccessibilityScaling()
  self.goArtifacts:SetLocalPosition(engine.Vector.New(4.217 + UI.GetAccessibilityScaling(0, -0.35), 6.25 + UI.GetAccessibilityScaling(0, 1), 0))
  self.goArtifacts:SetScale(UI.GetAccessibilityScaling(1, 1.15))
end
function Artifacts:Enter()
  self:UpdateAccessibilityScaling()
  if self:HaveTimer("setShowing") then
    self:StopTimer("setShowing")
  end
  if self:HaveTimer("hideDecal") then
    self:StopTimer("hideDecal")
  end
  self.showing = false
  for i = 1, #self.artifactDecals do
    local go = self.artifactDecals[i]
    go:Show()
    go:SetMaterialSwap("")
    UI.Anim(go, consts.AS_Reset, "", 0, 1)
  end
  self.questsOn:SubmenuEnter(self, questConsts.QUEST_CATEGORY_ARTIFACTS)
end
function Artifacts:Exit()
  self.questsOn:SubmenuExit(self)
  self.goArtifacts:Hide()
  if self:HaveTimer("setShowing") then
    self:StopTimer("setShowing")
  end
  if self:HaveTimer("delayedFadeIn") then
    self:StopTimer("delayedFadeIn")
  end
  if self:HaveTimer("fadeIn") then
    self:StopTimer("fadeIn")
  end
  for i = 1, #self.artifactDecals do
    local go = self.artifactDecals[i]
    UI.Anim(go, consts.AS_Reverse_NoReset, "", 2, 0, 1)
  end
  self.showing = false
  self:StartTimer("hideDecal", 0.5, function()
    self.goArtifactsDecal:Hide()
  end)
end
local artifactQuestToResourceFlag = {
  Quest_Artifacts_LostToys_Parent = "ArtifactToy",
  Quest_Artifacts_NorseMasks_Parent = "ArtifactMask",
  Quest_Artifacts_ShipHeads_Parent = "ArtifactShip",
  Quest_Artifacts_Alfheim_Parent = "ArtifactAlfheim",
  Quest_Artifacts_OrnateCups_Parent = "ArtifactCup",
  Quest_Artifacts_VikingHorns_Parent = "ArtifactHorn",
  Quest_Artifacts_Brooches_Parent = "ArtifactBrooch"
}
local artifactQuestToArtifactCount = {
  Quest_Artifacts_LostToys_Parent = 4,
  Quest_Artifacts_NorseMasks_Parent = 9,
  Quest_Artifacts_ShipHeads_Parent = 9,
  Quest_Artifacts_Alfheim_Parent = 6,
  Quest_Artifacts_OrnateCups_Parent = 6,
  Quest_Artifacts_VikingHorns_Parent = 6,
  Quest_Artifacts_Brooches_Parent = 5
}
local artifactToGameObjectIndex = {
  LostToyTroll = 1,
  LostToySpearGuy = 2,
  LostToyBoat = 3,
  LostToyHorse = 4,
  LostToyThor = 0,
  LostToyOrnament = 0,
  NorseMaskGhoul = 1,
  NorseMaskGoat = 2,
  NorseMaskTiki = 3,
  NorseMaskStraightBeard = 4,
  NorseMaskMustache = 5,
  NorseMaskFlatBeard = 6,
  NorseMaskCurlyBeard = 7,
  NorseMaskStoneFace = 8,
  NorseMaskReptile = 9,
  NorseMaskNoBeard = 0,
  NorseMaskHydra = 0,
  NorseMaskGroot = 0,
  ShipDragon = 1,
  ShipHook2 = 2,
  ShipHook = 3,
  ShipSeaHorse = 4,
  ShipTongue = 5,
  ShipGoldHook = 6,
  ShipHook3 = 7,
  ShipHook4 = 8,
  ShipGoldHook2 = 9,
  AlfheimPendant = 1,
  AlfheimMedallion = 2,
  AlfheimCurvy = 3,
  AlfheimSHook = 4,
  AlfheimHook = 5,
  AlfheimInsect = 6,
  CupDragon = 1,
  CupGoblet = 2,
  CupFeet = 3,
  CupHandle = 4,
  CupHolyGrail = 5,
  CupPintGlass = 6,
  HornExtension = 1,
  HornWorldTree = 2,
  HornUShape = 3,
  HornHorse = 4,
  HornHandle = 5,
  HornBigMouth = 6,
  BroochNeedle = 1,
  BroochRay = 2,
  BroochRuby = 3,
  BroochFancy = 4,
  BroochAnimal = 5
}
function Artifacts:delayedFadeIn()
  local allFullyStreamed = true
  for i = 1, #self.artifactDecals do
    local go = self.artifactDecals[i]
    if not go:CheckMaterialFullyStreamed() then
      allFullyStreamed = false
      go:RequestLoadHighMips(true)
    end
  end
  if allFullyStreamed then
    for i = 1, #self.artifactDecals do
      local go = self.artifactDecals[i]
      go:Show()
      UI.Anim(go, consts.AS_Forward, "", 1.5, 1, 0)
    end
    Audio.PlaySound("SND_UX_Pause_Menu_Page_Write")
    self:StartTimer("setShowing", 0.6666667, function()
      self.showing = true
    end)
  else
    self:RestartTimer("delayedFadeIn")
  end
end
function Artifacts:UpdateQuestInfo(questInfo)
  self.questsOn:UpdateFooterButtonPrompt(self.menu)
  if questInfo == nil or not questUtil.IsValidID(questUtil.GetQuestInfoQuestID(questInfo)) then
    self.goArtifacts:Hide()
    self.goArtifactsDecal:Hide()
    return
  end
  local questID = questUtil.GetQuestInfoQuestID(questInfo)
  self.goArtifacts:Show()
  self.goArtifactsDecal:Show()
  local foundArtifacts = resourceUtil.GetResources(resourceConsts.WALLET_KRATOS, {
    artifactQuestToResourceFlag[questID]
  }, {})
  local artifacts = {}
  for i = #foundArtifacts, 1, -1 do
    local artifact = foundArtifacts[i]
    if string.sub(artifact, 1, 7) ~= "Display" then
      local index = artifactToGameObjectIndex[artifact]
      if 0 < index then
        artifacts[index] = artifact
      end
    end
  end
  local fadeIn = function()
    local artifactCount = artifactQuestToArtifactCount[questID]
    UI.Anim(self.goArtifactsDecal, consts.AS_Forward, "journalArtifact_DecalsLayout", 0, artifactCount / 10)
    for i = 1, #self.artifactDecals do
      local go = self.artifactDecals[i]
      go:Hide()
      go:SetMaterialSwap(artifacts[i] or "")
      go:RequestLoadHighMips(true)
    end
    if not self:HaveTimer("delayedFadeIn") then
      self:StartTimer("delayedFadeIn", 0, function()
        self:delayedFadeIn()
      end)
    else
      self:RestartTimer("delayedFadeIn")
    end
  end
  if self:HaveTimer("setShowing") then
    self:StopTimer("setShowing")
  end
  if self:HaveTimer("delayedFadeIn") then
    self:StopTimer("delayedFadeIn")
  end
  if self:HaveTimer("fadeIn") then
    self:StopTimer("fadeIn")
  end
  for i = 1, #self.artifactDecals do
    local go = self.artifactDecals[i]
    UI.Anim(go, consts.AS_Reverse_NoReset, "", 2, 0, 1)
  end
  if self.showing then
    if not self:HaveTimer("clearShowing") then
      self:StartTimer("clearShowing", 0.5, function()
        self.showing = false
      end)
    end
    self:StartTimer("fadeIn", 0.5, fadeIn)
  else
    self:StartTimer("fadeIn", 0.2, fadeIn)
  end
  UI.SetText(self.thArtifactsTitle, questUtil.GetQuestInfoTitle(questInfo))
  local activeChildQuestId = questUtil.GetFocusQuestStepFromParent(questInfo.QuestID)
  if activeChildQuestId ~= nil then
    local questDesc, rewardDesc = GetObjectiveInfo(activeChildQuestId)
    UI.SetText(self.thArtifactsDesc, questDesc)
    UI.SetText(self.thArtifactsRewardDesc, rewardDesc)
  end
end
function Artifacts:UpdateFooterButtonPrompt()
  self.questsOn:UpdateFooterButtonPrompt(self.menu)
end
function Labors:Setup()
  self.questsOn = self:GetState("QuestsOn")
  self.questsOn:SubmenuSetup(self)
end
function Labors:Enter()
  self.questsOn:SubmenuEnter(self, questConsts.QUEST_CATEGORY_LABORS)
  self.questsOn:UpdateAccessibilityScaling()
end
function Labors:Exit()
  self.questsOn:SubmenuExit(self)
  self.questsOn.goQuests_Group:Hide()
  self.questsOn.goQuestInfo:Hide()
end
function Labors:UpdateQuestInfo(questInfo)
  self.questsOn:UpdateQuestInfo(self, questInfo)
end
function Labors:UpdateFooterButtonPrompt()
  self.questsOn:UpdateFooterButtonPrompt(self.menu)
end
function TreasureMaps:Setup()
  self.questsOn = self:GetState("QuestsOn")
  self.questsOn:SubmenuSetup(self)
  self.goTreasureMap = util.GetUiObjByName("TreasureMap_Group")
  self.goTreasureMapDecal = util.GetUiObjByName("TreasureMap_decal")
  self.thTreasureMapTitle = util.GetTextHandle(self.goTreasureMap, "QuestTitle1")
  self.thTreasureMapDesc = util.GetTextHandle(self.goTreasureMap, "QuestDesc1")
  self.thTreasureMapRewardDesc = util.GetTextHandle(self.goTreasureMap, "QuestRewardDesc1")
  local rewardsHeader = util.GetTextHandle(self.goTreasureMap, "RewardsHeader1")
  UI.SetText(rewardsHeader, util.GetLAMSMsg(lamsIDs.RewardsHeader))
end
function TreasureMaps:UpdateAccessibilityScaling()
  if UI.GetAccessibilityScaling == nil then
    return
  end
  self.questsOn:UpdateAccessibilityScaling()
  self.goTreasureMap:SetLocalPosition(engine.Vector.New(4.217 + UI.GetAccessibilityScaling(0, -0.35), 6.25 + UI.GetAccessibilityScaling(0, 1), 0))
  self.goTreasureMap:SetScale(UI.GetAccessibilityScaling(1, 1.15))
end
function TreasureMaps:Enter()
  self:UpdateAccessibilityScaling()
  if self:HaveTimer("setShowing") then
    self:StopTimer("setShowing")
  end
  if self:HaveTimer("hideDecal") then
    self:StopTimer("hideDecal")
  end
  self.showing = false
  self.goTreasureMapDecal:Show()
  self.goTreasureMapDecal:SetMaterialSwap("")
  UI.Anim(self.goTreasureMapDecal, consts.AS_Reset, "", 0, 1)
  self.questsOn:SubmenuEnter(self, questConsts.QUEST_CATEGORY_TREASURE_MAPS)
end
function TreasureMaps:Exit()
  self.questsOn:SubmenuExit(self)
  self.goTreasureMap:Hide()
  if self:HaveTimer("setShowing") then
    self:StopTimer("setShowing")
  end
  if self:HaveTimer("delayedFadeIn") then
    self:StopTimer("delayedFadeIn")
  end
  if self:HaveTimer("fadeIn") then
    self:StopTimer("fadeIn")
  end
  UI.Anim(self.goTreasureMapDecal, consts.AS_Reverse_NoReset, "", 2, 0, 1)
  self.showing = false
  self:StartTimer("hideDecal", 0.5, function()
    self.goTreasureMapDecal:Hide()
  end)
end
function TreasureMaps:delayedFadeIn()
  if self.goTreasureMapDecal:CheckMaterialFullyStreamed() then
    self.goTreasureMapDecal:Show()
    Audio.PlaySound("SND_UX_Pause_Menu_Page_Write")
    UI.Anim(self.goTreasureMapDecal, consts.AS_Forward, "", 1.5, 1, 0)
    self:StartTimer("setShowing", 0.6666667, function()
      self.showing = true
    end)
  else
    self.goTreasureMapDecal:RequestLoadHighMips(true)
    self:RestartTimer("delayedFadeIn")
  end
end
function TreasureMaps:UpdateQuestInfo(questInfo)
  self.questsOn:UpdateFooterButtonPrompt(self.menu)
  if questInfo == nil or not questUtil.IsValidID(questUtil.GetQuestInfoQuestID(questInfo)) then
    self.goTreasureMap:Hide()
    self.goTreasureMapDecal:Hide()
    return
  end
  local questID = questUtil.GetQuestInfoQuestID(questInfo)
  local fadeIn = function()
    self.goTreasureMap:Show()
    self.goTreasureMapDecal:Hide()
    self.goTreasureMapDecal:SetMaterialSwap(questID)
    self.goTreasureMapDecal:RequestLoadHighMips(true)
    if not self:HaveTimer("delayedFadeIn") then
      self:StartTimer("delayedFadeIn", 0, function()
        self:delayedFadeIn()
      end)
    else
      self:RestartTimer("delayedFadeIn")
    end
  end
  if self:HaveTimer("setShowing") then
    self:StopTimer("setShowing")
  end
  if self:HaveTimer("delayedFadeIn") then
    self:StopTimer("delayedFadeIn")
  end
  if self:HaveTimer("fadeIn") then
    self:StopTimer("fadeIn")
  end
  UI.Anim(self.goTreasureMapDecal, consts.AS_Reverse_NoReset, "", 2, 0, 1)
  if self.showing then
    if not self:HaveTimer("clearShowing") then
      self:StartTimer("clearShowing", 0.5, function()
        self.showing = false
      end)
    end
    self:StartTimer("fadeIn", 0.5, fadeIn)
  else
    self:StartTimer("fadeIn", 0.2, fadeIn)
  end
  UI.SetText(self.thTreasureMapTitle, questUtil.GetQuestInfoTitle(questInfo))
  UI.SetText(self.thTreasureMapDesc, questInfo.Desc)
  local activeChildQuestId = questUtil.GetFocusQuestStepFromParent(questInfo.QuestID)
  if activeChildQuestId ~= nil then
    local questDesc, rewardDesc, rewardsHeader = GetObjectiveInfo(activeChildQuestId)
    UI.SetText(self.thTreasureMapRewardDesc, rewardDesc)
  end
end
function TreasureMaps:UpdateFooterButtonPrompt()
  self.questsOn:UpdateFooterButtonPrompt(self.menu)
end
function QuestsMenu:OnSaveCheckpoint(tab)
end
function QuestsMenu:OnRestoreCheckpoint(tab)
end
