local tablex = require("core.tablex")
local consts = require("ui.consts")
local colors = require("ui.colors")
local questConsts = require("ui.questConsts")
local util = require("ui.util")
local QuestManager = game.QuestManager
local IsValidID = function(questID)
  return not util.IsStringNilOrEmpty(questID)
end
local QuestLoot_GetMin = function(questLoot)
  return questLoot.Min
end
local QuestLoot_GetMax = function(questLoot)
  return questLoot.Max
end
local QuestLoot_GetLamsID = function(questLoot)
  return questLoot.LamsID
end
local GetTrackingInfo = function(questID)
  local trackingInfo = {}
  if IsValidID(questID) then
    trackingInfo = QuestManager.GetTrackingInfo(questID)
  end
  return trackingInfo
end
local TrackQuest = function(questID)
  assert(IsValidID(questID), "Attempted to track invalid quest ID: " .. tostring(questID))
  return QuestManager.TrackQuest(questID)
end
local UntrackQuest = function(questID)
  assert(IsValidID(questID), "Attempted to stop tracking invalid quest ID: " .. tostring(questID))
  return QuestManager.UntrackQuest(questID)
end
local QuestTable_GetQuestID = function(questTable)
  return questTable.QuestId
end
local QuestTable_GetIsActive = function(questTable)
  return questTable.IsActive
end
local QuestTable_GetMarkers = function(questTable)
  return questTable.Markers
end
local TrackingInfo_GetRootQuestID = function(trackingInfo)
  return trackingInfo.RootQuest
end
local TrackingInfo_GetQuestTables = function(trackingInfo)
  return trackingInfo.Quests
end
local TrackingInfo_IsValid = function(trackingInfo)
  return trackingInfo ~= nil and type(trackingInfo.Quests) == "table"
end
local TrackingInfo_GetQuestTable = function(trackingInfo, questID)
  assert(trackingInfo ~= nil, "Nil tracking info passed into TrackingInfo_GetQuestTable!")
  assert(IsValidID(questID), "Invalid quest ID passed into TrackingInfo_GetQuestTable!")
  local desiredQuestTable
  local questTables = TrackingInfo_GetQuestTables(trackingInfo)
  for _, questTable in ipairs(questTables) do
    if QuestTable_GetQuestID(questTable) == questID then
      desiredQuestTable = questTable
      break
    end
  end
  return desiredQuestTable
end
local TrackingInfo_GetLastActiveQuestID = function(trackingInfo)
  local desiredQuestID
  if TrackingInfo_IsValid(trackingInfo) then
    local questTables = TrackingInfo_GetQuestTables(trackingInfo)
    for i = #questTables, 1, -1 do
      local questTable = questTables[i]
      if QuestTable_GetIsActive(questTable) then
        local currQuestID = QuestTable_GetQuestID(questTable)
        local titleLamsID = QuestManager.GetQuestTitleLams(currQuestID)
        if titleLamsID ~= 0 then
          desiredQuestID = currQuestID
          break
        end
      end
    end
  end
  return desiredQuestID
end
local TrackingInfo_GetTrackingState = function(trackingInfo, questID)
  local trackedState = questConsts.TRACKING_STATE_NONE
  if trackingInfo ~= nil then
    local questState = QuestManager.GetQuestState(questID)
    if questState == questConsts.QUEST_STATE_COMPLETE then
      trackedState = questConsts.TRACKING_STATE_FULLY_COMPLETE
    else
      local questTable = TrackingInfo_GetQuestTable(trackingInfo, questID)
      if questTable ~= nil then
        local isActive = QuestTable_GetIsActive(questTable)
        trackedState = isActive and questConsts.TRACKING_STATE_TRACKED or questConsts.TRACKING_STATE_NOT_TRACKED
      end
    end
  end
  return trackedState
end
local TrackingInfo_GetMarkers = function(trackingInfo, questID)
  assert(trackingInfo ~= nil, "Nil tracking info passed into TrackingInfo_GetMarkers!")
  assert(IsValidID(questID), "Invalid quest ID passed into TrackingInfo_GetMarkers!")
  local rootQuestID = TrackingInfo_GetRootQuestID(trackingInfo)
  local markers
  if questID == rootQuestID then
    local questTables = TrackingInfo_GetQuestTables(trackingInfo)
    for i = #questTables, 1, -1 do
      local questTable = questTables[i]
      markers = QuestTable_GetMarkers(questTable)
      if markers ~= nil and 0 < #markers then
        break
      end
    end
  else
    local questTable = TrackingInfo_GetQuestTable(trackingInfo, questID)
    markers = QuestTable_GetMarkers(questTable)
  end
  return markers
end
local GetQuestProgressAndGoal = function(questID)
  local hasProgress = false
  local progress = 0
  local goal = 0
  if questID ~= nil then
    hasProgress, progress, goal = QuestManager.GetQuestProgressAndGoal(questID)
  end
  return hasProgress, progress, goal
end
local HasFlag = function(questID, flag)
  assert(flag ~= nil, "questUtil.HasFlag called without a flag!")
  local hasFlag = false
  if IsValidID(questID) then
    hasFlag = QuestManager.QuestHasFlag(questID, flag)
  end
  return hasFlag
end
local GetQuestIcon = function(questID)
  local iconMaterialName = consts.EMPTY_MATERIAL_NAME
  for _, flag in ipairs(questConsts.QUEST_FLAGS) do
    if HasFlag(questID, flag) then
      iconMaterialName = flag
      break
    end
  end
  return iconMaterialName
end
local GetProgressInfo = function(questID)
  local progressInfo
  if IsValidID(questID) then
    local hasProgress, progress, goal = GetQuestProgressAndGoal(questID)
    if hasProgress == true and 0 < goal then
      progressInfo = {}
      progressInfo.Progress = progress <= goal and progress or goal
      progressInfo.Goal = goal
    end
  end
  return progressInfo
end
local GetRootQuestID = function(questID)
  local rootQuestID
  local trackingInfo = GetTrackingInfo(questID)
  if TrackingInfo_IsValid(trackingInfo) then
    rootQuestID = TrackingInfo_GetRootQuestID(trackingInfo)
  end
  return rootQuestID
end
local GetStatesByCategory = function(category)
  return questConsts.QUEST_INCLUDE_STATES[category]
end
local HasAnyStateInTable = function(questID, states)
  local hasState = false
  local currState = QuestManager.GetQuestState(questID)
  for _, state in ipairs(states) do
    if currState == state then
      hasState = true
      break
    end
  end
  return hasState
end
local GetFlagsByCategory = function(category)
  return questConsts.QUEST_INCLUDE_FLAGS[category]
end
local HasAnyFlagInTable = function(questID, flags)
  local hasFlag = false
  for _, flag in ipairs(flags) do
    if HasFlag(questID, flag) then
      hasFlag = true
      break
    end
  end
  return hasFlag
end
local GetSubStateName = function(questID)
  local subStateName
  for category, stateName in pairs(questConsts.QUEST_CATEGORY_SUB_STATES) do
    if HasAnyFlagInTable(questID, GetFlagsByCategory(category)) then
      subStateName = stateName
      break
    end
  end
  return subStateName
end
local IsMainQuest = function(questID)
  local isMainQuest = false
  if IsValidID(questID) then
    isMainQuest = HasAnyFlagInTable(questID, GetFlagsByCategory(questConsts.QUEST_CATEGORY_MAIN))
  end
  return isMainQuest
end
local IsSideQuest = function(questID)
  local isSideQuest = false
  if IsValidID(questID) then
    isSideQuest = HasAnyFlagInTable(questID, GetFlagsByCategory(questConsts.QUEST_CATEGORY_SIDE))
  end
  return isSideQuest
end
local IsTrackableSideQuest = function(questID)
  local isTrackableSideQuest = false
  if IsValidID(questID) then
    isTrackableSideQuest = HasAnyFlagInTable(questID, questConsts.TRACKABLE_SIDE_QUEST_FLAGS)
  end
  return isTrackableSideQuest
end
local IsTreasureMapQuest = function(questID)
  local isTreasureMapQuest = false
  if IsValidID(questID) then
    isTreasureMapQuest = HasAnyFlagInTable(questID, {
      questConsts.QUEST_FLAG_TREASURE_MAP
    })
  end
  return isTreasureMapQuest
end
local FindQuestForMarker = function(markerID)
  local hasQuest, questName = QuestManager.FindQuestForMarker(markerID)
  return hasQuest, questName
end
local GetQuestLoot = function(questID)
  local lootTable = {}
  if IsValidID(questID) then
    lootTable = QuestManager.GetQuestLoot(questID)
  end
  return lootTable
end
local GetQuestRewardText = function(questID)
  local rewardText = ""
  local lootTable = GetQuestLoot(questID)
  local lootCount = #lootTable
  if 0 < lootCount then
    if 1 < lootCount then
      rewardText = "Rewards:"
    else
      rewardText = "Reward:"
    end
    for _, loot in ipairs(lootTable) do
      local min = QuestLoot_GetMin(loot)
      local max = QuestLoot_GetMax(loot)
      local lamsID = QuestLoot_GetLamsID(loot)
      local numberText = min
      if min ~= max then
        numberText = numberText .. " - " .. max
      end
      rewardText = rewardText .. " " .. numberText .. " " .. util.GetLAMSMsg(lamsID)
    end
  end
  return rewardText
end
local GetProgressInfoProgress = function(progressInfo)
  return progressInfo.Progress
end
local GetProgressInfoGoal = function(progressInfo)
  return progressInfo.Goal
end
local GetQuestTitleFromID = function(questID)
  local titleLamsID = QuestManager.GetQuestTitleLams(questID)
  return util.GetLAMSMsg(titleLamsID)
end
local GetQuestDescriptionFromID = function(questID)
  local descLamsID = QuestManager.GetQuestDescriptionLams(questID)
  return util.GetLAMSMsg(descLamsID)
end
local CreateQuestInfo = function(questID, level, trackingInfo)
  local quest = {
    QuestID = questID,
    Title = GetQuestTitleFromID(questID),
    Desc = GetQuestDescriptionFromID(questID),
    State = QuestManager.GetQuestState(questID),
    Level = level,
    ProgressInfo = GetProgressInfo(questID),
    TrackingState = TrackingInfo_GetTrackingState(trackingInfo, questID)
  }
  return quest
end
local GetQuestInfoQuestID = function(questInfo)
  return questInfo.QuestID
end
local GetQuestInfoTitle = function(questInfo)
  if questInfo.ProgressInfo ~= nil then
    local progressInfo = questInfo.ProgressInfo
    return string.format(tostring(util.GetLAMSStringFromMsg(questInfo.Title)), GetProgressInfoProgress(progressInfo), GetProgressInfoGoal(progressInfo))
  end
  return questInfo.Title
end
local GetQuestInfoDesc = function(questInfo)
  return questInfo.Desc
end
local GetQuestInfoState = function(questInfo)
  return questInfo.State
end
local GetQuestInfoLevel = function(questInfo)
  return questInfo.Level
end
local GetQuestInfoProgressInfo = function(questInfo)
  return questInfo.ProgressInfo
end
local GetQuestInfoGetTrackingState = function(questInfo)
  return questInfo.TrackingState
end
local GetQuestInfoColor = function(questInfo)
  return colors.QUEST_STATES[GetQuestInfoState(questInfo)]
end
local QuestIsComplete = function(questInfo)
  return GetQuestInfoState(questInfo) == questConsts.QUEST_STATE_COMPLETE
end
local QuestIsActive = function(questId)
  local questState = QuestManager.GetQuestState(questId)
  return questState == questConsts.QUEST_STATE_ACTIVE
end
local GetQuestInfoProgressInfoText = function(questInfo)
  local text = ""
  if questInfo ~= nil then
    local progressInfo = GetQuestInfoProgressInfo(questInfo)
    if progressInfo ~= nil then
      text = GetProgressInfoProgress(progressInfo) .. " / " .. GetProgressInfoGoal(progressInfo)
    end
  end
  return text
end
local QuestInfo_HasQuestID = function(questInfo, questID)
  assert(questInfo ~= nil, "Invalid quest info passed into QuestInfo_HasQuestID")
  local hasQuestID = false
  if IsValidID(questID) then
    local questInfoQuestID = GetQuestInfoQuestID(questInfo)
    hasQuestID = questInfoQuestID == questID
  end
  return hasQuestID
end
local QuestInfoHasAnyStateInTable = function(questInfo, states)
  local hasState = false
  local currState = GetQuestInfoState(questInfo)
  for _, state in ipairs(states) do
    if currState == state then
      hasState = true
      break
    end
  end
  return hasState
end
local QuestInfoHasAnyFlagInTable = function(questInfo, flags)
  return HasAnyFlagInTable(GetQuestInfoQuestID(questInfo), flags)
end
local QuestInfoShouldAdd = function(questInfo, questFilter)
  local includeStateCheck = true
  local excludeStateCheck = true
  local includeFlagsCheck = true
  local excludeFlagsCheck = true
  if #questFilter._includeStates > 0 then
    includeStateCheck = QuestInfoHasAnyStateInTable(questInfo, questFilter._includeStates)
  end
  if 0 < #questFilter._excludeStates then
    excludeStateCheck = not QuestInfoHasAnyStateInTable(questInfo, questFilter._excludeStates)
  end
  if 0 < #questFilter._includeFlags then
    includeFlagsCheck = QuestInfoHasAnyFlagInTable(questInfo, questFilter._includeFlags)
  end
  if 0 < #questFilter._excludeFlags then
    excludeFlagsCheck = not QuestInfoHasAnyFlagInTable(questInfo, questFilter._excludeFlags)
  end
  return includeStateCheck == true and excludeStateCheck == true and includeFlagsCheck == true and excludeFlagsCheck == true
end
local QuestInfoShouldKeepRecursing = function(questInfo)
  return questInfo ~= nil and (GetQuestInfoState(questInfo) == questConsts.QUEST_STATE_ACTIVE or GetQuestInfoState(questInfo) == questConsts.QUEST_STATE_COMPLETE)
end
local QuestInfoTableGetQuestTrackingState = function(questInfoTable, questID)
  local trackingState = questConsts.TRACKING_STATE_NONE
  for _, questInfo in ipairs(questInfoTable) do
    if GetQuestInfoQuestID(questInfo) == questID then
      trackingState = GetQuestInfoGetTrackingState(questInfo)
    end
  end
  return trackingState
end
local GetFocusQuestStepFromParent = function(parentQuestId)
  assert(QuestManager.IsActiveRootQuestId(parentQuestId), "Quest Id passed into QuestUtil:GetFocusQuestStepFromParent is not a parent quest!")
  if QuestManager.GetQuestState(parentQuestId) == questConsts.QUEST_STATE_COMPLETE then
    local childrenQuestIds = QuestManager.GetChildrenQuestIds(parentQuestId)
    local currentQuestId = childrenQuestIds[1]
    if currentQuestId ~= nil then
      while QuestManager.GetQuestState(currentQuestId) == questConsts.QUEST_STATE_COMPLETE do
        childrenQuestIds = QuestManager.GetChildrenQuestIds(currentQuestId)
        if childrenQuestIds[1] == nil then
          break
        end
        currentQuestId = childrenQuestIds[1]
      end
    end
    return currentQuestId
  end
  if not QuestIsActive(parentQuestId) then
    return nil
  end
  local childrenQuestIds = QuestManager.GetChildrenQuestIds(parentQuestId)
  local currentQuestId = childrenQuestIds[1]
  while currentQuestId ~= nil and not QuestIsActive(currentQuestId) do
    childrenQuestIds = QuestManager.GetChildrenQuestIds(currentQuestId)
    currentQuestId = childrenQuestIds[1]
  end
  return currentQuestId
end
local AddQuestChildren = function(questInfoTable, questId, questFilter)
  local trackingInfo = GetTrackingInfo(questId)
  local questInfo = CreateQuestInfo(questId, 0, trackingInfo)
  local checkedIndex = #questInfoTable
  if QuestInfoShouldAdd(questInfo, questFilter) then
    tablex.FastInsert(questInfoTable, questInfo, #questInfoTable + 1)
  end
  while checkedIndex ~= #questInfoTable do
    checkedIndex = checkedIndex + 1
    local curQuestInfo = questInfoTable[checkedIndex]
    local curQuestId = curQuestInfo.QuestID
    if QuestInfoShouldKeepRecursing(curQuestInfo) then
      local insertIndex = checkedIndex
      local parentLevel = curQuestInfo.Level
      local children = QuestManager.GetChildrenQuestIds(curQuestId)
      for _, childQuest in ipairs(children) do
        local childTrackingInfo = GetTrackingInfo(childQuest)
        local childQuestInfo = CreateQuestInfo(childQuest, parentLevel + 1, childTrackingInfo)
        if QuestInfoShouldAdd(childQuestInfo, questFilter) then
          insertIndex = insertIndex + 1
          tablex.FastInsert(questInfoTable, childQuestInfo, insertIndex)
        end
      end
    end
  end
end
local CreateChildQuestFilter = function(questFilter)
  local childQuestFilter = {}
  for key, value in pairs(questFilter) do
    childQuestFilter[key] = value
  end
  local hasCompleted = false
  for _, value in ipairs(childQuestFilter._includeStates) do
    if value == questConsts.QUEST_STATE_COMPLETE then
      hasCompleted = true
    end
  end
  local desiredStates = childQuestFilter._includeStates
  if not hasCompleted then
    tablex.FastInsert(childQuestFilter._includeStates, questConsts.QUEST_STATE_COMPLETE, #desiredStates + 1)
  end
  return childQuestFilter
end
local GetAllActiveQuestInfo = function(questFilter)
  local rootQuests = QuestManager.GetActiveRootQuestIds()
  local questInfoTable = {}
  for _, questId in ipairs(rootQuests) do
    AddQuestChildren(questInfoTable, questId, questFilter)
  end
  return questInfoTable
end
local GetAllActiveRootQuestInfo = function(questFilter)
  local rootQuests = QuestManager.GetActiveRootQuestIds()
  local questInfoTable = {}
  for _, rootQuestID in ipairs(rootQuests) do
    local trackingInfo = GetTrackingInfo(rootQuestID)
    local rootQuestInfo = CreateQuestInfo(rootQuestID, 0, trackingInfo)
    if TrackingInfo_IsValid(trackingInfo) and QuestInfoShouldAdd(rootQuestInfo, questFilter) then
      tablex.FastInsert(questInfoTable, rootQuestInfo, #questInfoTable + 1)
    end
  end
  return questInfoTable
end
local CreateQuestFilter = function(includeStates, excludeStates, includeFlags, excludeFlags)
  return {
    _includeStates = includeStates,
    _excludeStates = excludeStates,
    _includeFlags = includeFlags,
    _excludeFlags = excludeFlags
  }
end
local IsQuestTracked = function(activeQuestID)
  local isTracked = false
  local trackingInfo = QuestManager.GetTrackingInfo(activeQuestID)
  if IsMainQuest(activeQuestID) then
    isTracked = trackingInfo ~= nil
  elseif TrackingInfo_IsValid(trackingInfo) then
    local questTables = TrackingInfo_GetQuestTables(trackingInfo)
    local firstQuestTable = questTables[1]
    if firstQuestTable ~= nil then
      isTracked = QuestTable_GetIsActive(firstQuestTable)
    end
  end
  return isTracked
end
local GetActiveRootQuestsByCategory = function(questCategory)
  local categoryRootQuests = {}
  local allActiveRootQuestIDs = QuestManager.GetActiveRootQuestIds()
  for _, rootQuestID in ipairs(allActiveRootQuestIDs) do
    assert(IsValidID(rootQuestID), "Invalid Quest ID found in table returned by QuestManager.GetActiveRootQuestIds!")
    if HasAnyFlagInTable(rootQuestID, GetFlagsByCategory(questCategory)) then
      tablex.FastInsert(categoryRootQuests, rootQuestID, #categoryRootQuests + 1)
    end
  end
  return categoryRootQuests
end
local FindCurrentlyTrackedRootQuestIDByCategory = function(questCategory)
  local categoryRootQuests = GetActiveRootQuestsByCategory(questCategory)
  for _, questID in ipairs(categoryRootQuests) do
    if IsQuestTracked(questID) then
      return questID
    end
  end
  return nil
end
local GetActiveSideQuests = function()
  return GetActiveRootQuestsByCategory(questConsts.QUEST_CATEGORY_SIDE)
end
local FindCurrentlyTrackedSideQuestID = function()
  return FindCurrentlyTrackedRootQuestIDByCategory(questConsts.QUEST_CATEGORY_SIDE)
end
local UntrackSideQuest = function(questID)
  local trackingInfo = QuestManager.GetTrackingInfo(questID)
  QuestManager.UntrackQuest(trackingInfo.RootQuest)
end
local TrackSideQuest = function(questID)
  if QuestManager.GetQuestStateInt(questID) ~= tweaks.eQstState.kQS_Active then
    return
  end
  local curTrackedQuest = FindCurrentlyTrackedSideQuestID()
  if IsValidID(curTrackedQuest) then
    UntrackSideQuest(curTrackedQuest)
  end
  local trackingInfo = QuestManager.GetTrackingInfo(questID)
  QuestManager.TrackQuest(trackingInfo.RootQuest)
  if QuestManager.AddMarkersToCompass ~= nil then
    QuestManager.AddMarkersToCompass(questID)
  end
end
local AddMarkersToCompassFromSequence = function(questID)
  if game.QuestManager.AddMarkersToCompass == nil then
    return
  end
  if questID == nil or not IsMainQuest(questID) and (not IsTrackableSideQuest(questID) or not IsQuestTracked(questID)) then
    return
  end
  game.QuestManager.AddMarkersToCompass(questID)
end
return {
  IsValidID = IsValidID,
  QuestLoot_GetMin = QuestLoot_GetMin,
  QuestLoot_GetMax = QuestLoot_GetMax,
  QuestLoot_GetLamsID = QuestLoot_GetLamsID,
  GetTrackingInfo = GetTrackingInfo,
  TrackQuest = TrackQuest,
  UntrackQuest = UntrackQuest,
  TrackingInfo_GetRootQuestID = TrackingInfo_GetRootQuestID,
  TrackingInfo_IsValid = TrackingInfo_IsValid,
  TrackingInfo_GetLastActiveQuestID = TrackingInfo_GetLastActiveQuestID,
  TrackingInfo_GetTrackingState = TrackingInfo_GetTrackingState,
  TrackingInfo_GetMarkers = TrackingInfo_GetMarkers,
  HasFlag = HasFlag,
  GetQuestIcon = GetQuestIcon,
  GetProgressInfo = GetProgressInfo,
  GetRootQuestID = GetRootQuestID,
  GetStatesByCategory = GetStatesByCategory,
  GetFlagsByCategory = GetFlagsByCategory,
  GetSubStateName = GetSubStateName,
  IsMainQuest = IsMainQuest,
  IsSideQuest = IsSideQuest,
  IsTrackableSideQuest = IsTrackableSideQuest,
  IsTreasureMapQuest = IsTreasureMapQuest,
  GetFocusQuestStepFromParent = GetFocusQuestStepFromParent,
  FindQuestForMarker = FindQuestForMarker,
  GetQuestLoot = GetQuestLoot,
  GetQuestRewardText = GetQuestRewardText,
  GetProgressInfoProgress = GetProgressInfoProgress,
  GetProgressInfoGoal = GetProgressInfoGoal,
  QuestInfoTableGetQuestTrackingState = QuestInfoTableGetQuestTrackingState,
  GetQuestTitleFromID = GetQuestTitleFromID,
  GetQuestDescriptionFromID = GetQuestDescriptionFromID,
  CreateQuestInfo = CreateQuestInfo,
  GetQuestInfoQuestID = GetQuestInfoQuestID,
  GetQuestInfoTitle = GetQuestInfoTitle,
  GetQuestInfoDesc = GetQuestInfoDesc,
  GetQuestInfoState = GetQuestInfoState,
  GetQuestInfoLevel = GetQuestInfoLevel,
  GetQuestInfoProgressInfo = GetQuestInfoProgressInfo,
  GetQuestInfoGetTrackingState = GetQuestInfoGetTrackingState,
  GetQuestInfoColor = GetQuestInfoColor,
  QuestIsComplete = QuestIsComplete,
  GetQuestInfoProgressInfoText = GetQuestInfoProgressInfoText,
  QuestInfo_HasQuestID = QuestInfo_HasQuestID,
  GetAllActiveQuestInfo = GetAllActiveQuestInfo,
  GetAllActiveRootQuestInfo = GetAllActiveRootQuestInfo,
  CreateQuestFilter = CreateQuestFilter,
  CreateChildQuestFilter = CreateChildQuestFilter,
  AddQuestChildren = AddQuestChildren,
  IsQuestTracked = IsQuestTracked,
  FindCurrentlyTrackedRootQuestIDByCategory = FindCurrentlyTrackedRootQuestIDByCategory,
  GetActiveSideQuests = GetActiveSideQuests,
  FindCurrentlyTrackedSideQuestID = FindCurrentlyTrackedSideQuestID,
  UntrackSideQuest = UntrackSideQuest,
  TrackSideQuest = TrackSideQuest,
  AddMarkersToCompassFromSequence = AddMarkersToCompassFromSequence,
  HasAnyFlagInTable = HasAnyFlagInTable
}
