local tablex = require("core.tablex")
local colors = require("ui.colors")
local consts = require("ui.consts")
local lamsIDs = require("ui.lamsConsts")
local pickupConsts = require("ui.pickupConsts")
local resourceConsts = require("ui.resourceConsts")
local util = require("ui.util")
local Pickup = game.Pickup
local Player = game.Player
local AI = game.AI
local UI = game.UI
local pickupSlotNames = {
  [pickupConsts.TAG_PICKUP_KRATOS] = {
    pickupConsts.Slot_PrimaryWeapon,
    pickupConsts.Slot_Blades,
    pickupConsts.Slot_ArmorChest,
    pickupConsts.Slot_ArmorWrist,
    pickupConsts.Slot_ArmorLegs,
    pickupConsts.Slot_ArmorTrinket
  },
  [pickupConsts.TAG_PICKUP_SON] = {
    pickupConsts.Slot_PrimaryWeapon,
    pickupConsts.Slot_SonArmor,
    pickupConsts.Slot_SecondaryWeapon
  }
}
local weaponUpgradeSlotNames = {
  [pickupConsts.TAG_PICKUP_KRATOS] = {
    [pickupConsts.Slot_PrimaryWeapon] = {
      pickupConsts.Slot_WeaponSpecial_Light,
      pickupConsts.Slot_WeaponSpecial_Heavy,
      pickupConsts.Slot_WeaponComponent
    },
    [pickupConsts.Slot_Blades] = {
      pickupConsts.Slot_WeaponSpecial_Blades_Light,
      pickupConsts.Slot_WeaponSpecial_Blades_Heavy,
      pickupConsts.Slot_WeaponComponent_Blades
    },
    [pickupConsts.Slot_ArmorShield] = {}
  },
  [pickupConsts.TAG_PICKUP_SON] = {
    [pickupConsts.Slot_PrimaryWeapon] = {
      pickupConsts.Slot_SonSpecial
    }
  }
}
local weaponSpecialSlotsByWeapon = {
  [pickupConsts.Axe] = {
    [pickupConsts.Slot_WeaponSpecial_Light] = true,
    [pickupConsts.Slot_WeaponSpecial_Heavy] = true
  },
  [pickupConsts.Bare] = {},
  [pickupConsts.Blades] = {
    [pickupConsts.Slot_WeaponSpecial_Blades_Light] = true,
    [pickupConsts.Slot_WeaponSpecial_Blades_Heavy] = true
  }
}
local IsValidSlotName = function(slotName)
  return not util.IsStringNilOrEmpty(slotName) and slotName ~= pickupConsts.Slot_Invalid
end
local GetPickupSlotNames = function(character)
  return pickupSlotNames[character]
end
local GetWeaponUpgradeSlotNames = function(character, pickupSlotName)
  assert(character ~= nil, "Attempting to call GetWeaponUpgradeSlotNames without a character.")
  assert(IsValidSlotName(pickupSlotName), "Attempting to call GetWeaponUpgradeSlotNames on Invalid slot.")
  return weaponUpgradeSlotNames[character][pickupSlotName]
end
local GetPickupNameInSlot = function(creature, slotName)
  assert(creature ~= nil, "Attempting to get pickup in slot " .. tostring(slotName) .. " on a non-existent creature.")
  assert(IsValidSlotName(slotName), "Attempting to get pickup in Invalid slot.")
  local pickupName
  local creatureName = creature:GetName()
  if creatureName == consts.CREATURE_NAME_SON and slotName == pickupConsts.Slot_SonSpecial then
    creature = Player.FindPlayer()
  end
  if creature:PickupIsSlotUsed(slotName) then
    pickupName = creature:PickupGetPickupNameInSlot(slotName)
  end
  return pickupName
end
local GetSlotDisplayName = function(slotName)
  local displayName = ""
  if IsValidSlotName(slotName) then
    displayName = util.GetLAMSMsg(pickupConsts.Slot_DisplayNameIDs[slotName], slotName)
  end
  return displayName
end
local GetSlotIcon = function(slotName)
  local macroIcon = ""
  if IsValidSlotName(slotName) then
    macroIcon = "[" .. slotName .. "]"
  end
  return macroIcon
end
local GetSlotSpecialMeterDefaultColor = function(pickupSlotName)
  local specialMeterColor = colors.SPECIAL_METER_DEFAULT[pickupConsts.Slot_Invalid]
  if IsValidSlotName(pickupSlotName) and colors.SPECIAL_METER_DEFAULT[pickupSlotName] ~= nil then
    specialMeterColor = colors.SPECIAL_METER_DEFAULT[pickupSlotName]
  end
  return specialMeterColor
end
local GetSlotSpecialMeterCooldownColor = function(pickupSlotName)
  local specialMeterColor = colors.SPECIAL_METER_COOLDOWN[pickupConsts.Slot_Invalid]
  if IsValidSlotName(pickupSlotName) and colors.SPECIAL_METER_COOLDOWN[pickupSlotName] ~= nil then
    specialMeterColor = colors.SPECIAL_METER_COOLDOWN[pickupSlotName]
  end
  return specialMeterColor
end
local GetWeaponSpecialSlots = function(weaponName)
  return weaponSpecialSlotsByWeapon[weaponName]
end
local WeaponSpecialSlotDisplayForWeapon = function(pickupSlotName, weaponName)
  local isActiveSpecialSlot = false
  local weaponSpecialSlots = GetWeaponSpecialSlots(weaponName)
  if weaponSpecialSlots ~= nil then
    isActiveSpecialSlot = weaponSpecialSlots[pickupSlotName] ~= nil
  end
  return isActiveSpecialSlot
end
local WeaponSpecialSlotBelongsToWeapon = function(pickupSlotName, weaponName)
  local isActiveSpecialSlot = false
  local weaponSpecialSlots = GetWeaponSpecialSlots(weaponName)
  if weaponSpecialSlots ~= nil then
    isActiveSpecialSlot = weaponSpecialSlots[pickupSlotName] == true
  end
  return isActiveSpecialSlot
end
local GetAvailablePickupSlotNames = function(character)
  local availablePickupSlotNames = {}
  local availablePickupSlotIndex = 1
  local allPickupSlotNames = GetPickupSlotNames(character)
  for _, pickupSlotName in ipairs(allPickupSlotNames) do
    local isPrimaryWeaponSlot = pickupSlotName == pickupConsts.Slot_PrimaryWeapon
    local isBladesSlot = pickupSlotName == pickupConsts.Slot_Blades
    local isQuiverSlot = pickupSlotName == pickupConsts.Slot_SecondaryWeapon
    if not isBladesSlot and not isPrimaryWeaponSlot and not isQuiverSlot then
      tablex.FastInsert(availablePickupSlotNames, pickupSlotName, availablePickupSlotIndex)
      availablePickupSlotIndex = availablePickupSlotIndex + 1
    end
  end
  return availablePickupSlotNames
end
local Exists = function(pickupName)
  return Pickup.Exists(pickupName)
end
local IsValidName = function(pickupName)
  local isValid = not util.IsStringNilOrEmpty(pickupName)
  if isValid then
    assert(Exists(pickupName), "Pickup " .. pickupName .. " does not exist!")
  end
  return isValid
end
local GetDisplayName = function(pickupName)
  local displayName = tostring(pickupName) .. " Display Name Not Found"
  if IsValidName(pickupName) == true then
    local displayNameId
    if type(pickupName) == "string" and pickupName == pickupConsts.Shield then
      displayNameId = lamsIDs.Shield
    else
      displayNameId = Pickup.GetDisplayNameId(pickupName)
    end
    if 0 < displayNameId then
      displayName = util.GetLAMSMsg(displayNameId, pickupName)
    end
  end
  return displayName
end
local GetDescription = function(pickupName)
  local desc = pickupName .. " Description Not Found"
  if IsValidName(pickupName) then
    local descriptionId = Pickup.GetDisplayDescriptionId(pickupName)
    if 0 < descriptionId then
      desc = util.GetLAMSMsg(descriptionId, pickupName)
    end
  end
  return desc
end
local emptySlotDescriptions = {
  [pickupConsts.Slot_ArmorWrist] = lamsIDs.EmptyMessage_WristArmor,
  [pickupConsts.Slot_ArmorTrinket] = lamsIDs.EmptyMessage_Talisman,
  [pickupConsts.Slot_WeaponSpecial_Light] = lamsIDs.EmptySlot_WeaponSpecial,
  [pickupConsts.Slot_WeaponSpecial_Heavy] = lamsIDs.EmptySlot_WeaponSpecial,
  [pickupConsts.Slot_WeaponSpecial_Blades_Light] = lamsIDs.EmptySlot_WeaponSpecial,
  [pickupConsts.Slot_WeaponSpecial_Blades_Heavy] = lamsIDs.EmptySlot_WeaponSpecial,
  [pickupConsts.Slot_SonSpecial] = lamsIDs.EmptySlot_SonSpecial
}
local GetEmptySlotDescription = function(pickupName)
  local desc = ""
  if pickupName ~= nil then
    local returnLams = emptySlotDescriptions[pickupName]
    if returnLams ~= nil then
      desc = util.GetLAMSMsg(returnLams)
    end
  end
  return desc
end
local GetRarityColor = function(rarity)
  local color
  if rarity ~= nil then
    color = colors.RARITY[rarity]
  end
  if color == nil then
    color = colors.WHITE
  end
  return color
end
local HasTag = function(pickupName, tag)
  local hasTag = false
  if IsValidName(pickupName) and tag ~= nil then
    hasTag = Pickup.HasTags(pickupName, tag)
  end
  return hasTag
end
local HasSkillTree = function(pickupName)
  local hasSkillTree = false
  if IsValidName(pickupName) then
    hasSkillTree = Pickup.HasTags(pickupName, pickupConsts.TAG_PICKUP_HAS_SKILL_TREE)
  end
  return hasSkillTree
end
local GetSlotName = function(pickupName)
  local slotName = pickupConsts.Slot_Invalid
  if IsValidName(pickupName) then
    if pickupName == pickupConsts.Shield then
      slotName = pickupConsts.Slot_ArmorShield
    else
      slotName = Pickup.GetSlotName(pickupName)
    end
  end
  return slotName
end
local IsInSlot = function(creature, pickupName)
  local isInSlot = false
  if creature ~= nil and IsValidName(pickupName) then
    local currPickupSlotName = GetSlotName(pickupName)
    local pickupInSlot = GetPickupNameInSlot(creature, currPickupSlotName)
    isInSlot = pickupInSlot == pickupName
  end
  return isInSlot
end
local GetProfileStage = function(pickupName)
  local stage = 0
  if IsValidName(pickupName) == true then
    stage = Pickup.GetProfileStage(pickupName)
  end
  return stage
end
local GetStage = function(pickupName, creature)
  local stage = 0
  if IsValidName(pickupName) == true then
    if creature ~= nil and creature:PickupIsAcquired(pickupName) then
      stage = creature:PickupGetStage(pickupName)
    else
      stage = Pickup.GetProfileStage(pickupName)
    end
  end
  return stage
end
local GetMaxStage = function(pickupName)
  local stage = 0
  if IsValidName(pickupName) == true then
    stage = Pickup.GetMaxStage(pickupName)
  end
  return stage
end
local GetStageDisplayName = function(stage)
  return util.GetLAMSMsg(lamsIDs["RomanNumeral_" .. tostring(stage)])
end
local GetTier = function(pickupName)
  local tier = GetProfileStage(pickupName) + 1
  return util.Clamp(tier, 1, resourceConsts.MAX_TIER)
end
local GetLevel = function(pickupName)
  local level = ""
  if IsValidName(pickupName) then
    local tier = GetTier(pickupName)
    local lamsID = lamsIDs["RomanNumeral_" .. tier]
    level = util.GetLAMSMsg(lamsID, pickupName)
  end
  return level
end
local GetCreatureFromCharacter = function(characterTag)
  assert(characterTag ~= nil)
  local creature
  if characterTag == pickupConsts.TAG_PICKUP_KRATOS then
    creature = Player.FindPlayer()
  elseif characterTag == pickupConsts.TAG_PICKUP_SON then
    creature = AI.FindSon()
  end
  return creature
end
local GetCharacterFromCreature = function(creature)
  assert(creature ~= nil, "nil creature passed into pickupUtil:GetCharacterFromCreature")
  local creatureName = creature:GetName()
  if creatureName == consts.CREATURE_NAME_KRATOS then
    return pickupConsts.TAG_PICKUP_KRATOS
  elseif creatureName == consts.CREATURE_NAME_SON then
    return pickupConsts.TAG_PICKUP_SON
  else
    assert(false, "Else case got hit in pickupUtil:GetCharacterFromCreature that should never get hit. CreatureName was: " .. tostring(creatureName))
  end
end
local IsWeaponSpecialSlot = function(pickupID)
  assert(type(pickupID == "string"))
  local weaponSpecialSlotNames = pickupConsts.WeaponSpecialsSlots
  local isWeaponSpecial = false
  for _, currentID in ipairs(weaponSpecialSlotNames) do
    if currentID == pickupID then
      isWeaponSpecial = true
      break
    end
  end
  return isWeaponSpecial
end
local IsPrimaryWeapon = function(pickupName)
  local isPrimaryWeapon = false
  if IsValidName(pickupName) then
    local pickupSlot = GetSlotName(pickupName)
    isPrimaryWeapon = pickupSlot == pickupConsts.Slot_PrimaryWeapon
  end
  return isPrimaryWeapon
end
local IsWeapon = function(pickupName)
  local isWeapon = false
  if IsValidName(pickupName) then
    local pickupSlot = GetSlotName(pickupName)
    isWeapon = pickupSlot == pickupConsts.Slot_PrimaryWeapon or pickupSlot == pickupConsts.Slot_Blades
  end
  return isWeapon
end
local IsArmor = function(pickupName)
  local isArmor = false
  if IsValidName(pickupName) then
    local pickupSlot = GetSlotName(pickupName)
    if pickupSlot == pickupConsts.Slot_ArmorChest or pickupSlot == pickupConsts.Slot_ArmorLegs or pickupSlot == pickupConsts.Slot_ArmorWrist or pickupSlot == pickupConsts.Slot_ArmorTrinket or pickupSlot == pickupConsts.Slot_SonArmor then
      isArmor = true
    end
  end
  return isArmor
end
local IsWeaponSpecial = function(pickupName)
  if IsValidName(pickupName) then
    local pickupsSlot = GetSlotName(pickupName)
    for _, slot in ipairs(pickupConsts.WEAPONMENU_WEAPON_SPECIAL_SLOTS) do
      if slot == pickupsSlot then
        return true
      end
    end
  end
  return false
end
local IsWeaponComponent = function(pickupName)
  local isComponent = false
  if IsValidName(pickupName) then
    local pickupSlot = GetSlotName(pickupName)
    isComponent = pickupSlot == pickupConsts.Slot_WeaponComponent or pickupSlot == pickupConsts.Slot_WeaponComponent_Blades
  end
  return isComponent
end
local IsBladesSpecialOrComponent = function(pickupName)
  if IsValidName(pickupName) then
    local pickupSlot = GetSlotName(pickupName)
    return pickupSlot == pickupConsts.Slot_WeaponSpecial_Blades_Light or pickupSlot == pickupConsts.Slot_WeaponSpecial_Blades_Heavy or pickupSlot == pickupConsts.Slot_WeaponComponent_Blades
  end
  return false
end
local IsNew = function(pickupName)
  local isNew = false
  if IsValidName(pickupName) then
    isNew = UI.HasNotification(consts.NotificationTypes.Resource, pickupName)
  end
  return isNew
end
local IsEquipped = function(pickupName)
  local slotName = GetSlotName(pickupName)
  local creature_Son = GetCreatureFromCharacter(pickupConsts.TAG_PICKUP_SON)
  if IsInSlot(creature_Son, pickupName) == true then
    return true
  end
  local creature_Kratos = GetCreatureFromCharacter(pickupConsts.TAG_PICKUP_KRATOS)
  if IsInSlot(creature_Kratos, pickupName) == true then
    return true
  end
  return false
end
local GetIcon = function(pickupName)
  local iconMacro = ""
  if IsValidName(pickupName) then
    if IsWeapon(pickupName) then
      iconMacro = "[SkillTree" .. pickupName .. "]"
    elseif IsArmor(pickupName) then
      local slotName = GetSlotName(pickupName)
      iconMacro = GetSlotIcon(slotName)
    else
      iconMacro = "[" .. pickupName .. "]"
    end
  end
  return iconMacro
end
local GetRuneSocketCount = function(pickupName, stageOverride)
  if stageOverride ~= nil then
    assert(type(stageOverride) == "number" and -1 < stageOverride)
  end
  local socketCount = 0
  if IsValidName(pickupName) == true then
    local stage = stageOverride ~= nil and stageOverride or Pickup.GetProfileStage(pickupName)
    if stage < 0 then
      stage = 0
    end
    if 0 <= stage then
      socketCount = Pickup.GetSocketCount(pickupName, stage)
      assert(socketCount <= pickupConsts.MAX_SOCKET_COUNT, "Pickup " .. pickupName .. " defined with too many sockets! Has " .. socketCount .. ", max socket count is: " .. pickupConsts.MAX_SOCKET_COUNT)
    end
  end
  return socketCount
end
local GetRuneSocketCountPreview = function(pickupName, stageOverride)
  if stageOverride ~= nil then
    local nextStageExists = stageOverride < GetMaxStage(pickupName)
    if nextStageExists then
      return GetRuneSocketCount(pickupName, stageOverride + 1)
    end
  end
  return 0
end
local GetAttribute = function(pickupName, attributeName, stage)
  local value = 0
  if IsValidName(pickupName) and not util.IsStringNilOrEmpty(attributeName) then
    if stage then
      value = Pickup.GetAttribute(pickupName, attributeName, stage)
    else
      value = Pickup.GetAttribute(pickupName, attributeName)
    end
    if value == nil then
      value = 0
    end
  end
  return value
end
local GetPickupAttributes = function(pickupName)
  local attributeTable = {}
  for index, attributesName in ipairs(pickupConsts.Attributes) do
    attributeTable[index] = GetAttribute(pickupName, attributesName)
  end
  return attributeTable
end
local HasPerks = function(pickupName)
  return false
end
local PickupAcquire = function(creature, pickupName, stage, fromMenu)
  assert(creature ~= nil, "Attempted to acquire a pickup without a creature!")
  if stage == nil then
    stage = GetProfileStage(pickupName)
    if stage < 0 then
      print("ERROR: Attempted to equip a pickup with stage -1 this likely means the player didn't possess the associated resource with pickup: " .. tostring(pickupName))
      stage = 0
    end
  end
  creature:PickupAcquire(pickupName, stage, fromMenu)
end
local PickupAcquireWhileOnCooldown = function(creature, pickupName, stage, fromMenu)
  assert(creature ~= nil, "Attempted to acquire a pickup without a creature!")
  if stage == nil then
    stage = GetProfileStage(pickupName)
    if stage < 0 then
      print("ERROR: Attempted to equip a pickup with stage -1 this likely means the player didn't possess the associated resource with pickup: " .. tostring(pickupName))
      stage = 0
    end
  end
  if creature.PickupUpgradeWhileInCooldown then
    creature:PickupUpgradeWhileInCooldown(pickupName, stage, fromMenu)
  else
    creature:PickupAcquire(pickupName, stage, fromMenu)
  end
end
local IsUpgradeAllowed = function(pickupSlotItem)
  local isUpgradeAllowed = false
  if pickupSlotItem == nil or type(pickupSlotItem) == "table" then
    return false
  end
  if IsArmor(pickupSlotItem) == true then
    local socketCount = GetRuneSocketCount(pickupSlotItem)
    isUpgradeAllowed = 0 < socketCount
  end
  return isUpgradeAllowed
end
local ShouldUseMaterialSwap = function(pickupName)
  local shouldUseMaterialSwap = false
  if pickupName == pickupConsts.SonQuiver then
    pickupName = pickupConsts.SonBow
  end
  if IsValidName(pickupName) then
    local pickupSlot = GetSlotName(pickupName)
    if IsValidSlotName(pickupSlot) and (pickupSlot == pickupConsts.Slot_ArmorChest or pickupSlot == pickupConsts.Slot_ArmorLegs or pickupSlot == pickupConsts.Slot_ArmorWrist or pickupSlot == pickupConsts.Slot_ArmorShield or pickupSlot == pickupConsts.Slot_SonArmor or pickupSlot == pickupConsts.Slot_PrimaryWeapon or pickupSlot == pickupConsts.Slot_Blades) then
      shouldUseMaterialSwap = true
    end
  end
  return shouldUseMaterialSwap
end
local CheckCharacterPickupID = function(id)
  assert(id == pickupConsts.TAG_PICKUP_KRATOS or id == pickupConsts.TAG_PICKUP_SON, "Pickup ID was not pickupConsts.TAG_PICKUP_KRATOS or pickupConsts.TAG_PICKUP_SON. Value was: " .. tostring(id))
end
local GetUICreatureGOName = function(character)
  assert(character ~= nil, "'character' variable passed into PickupUtil:GetUICreatureGOName was nil.")
  if character == pickupConsts.TAG_PICKUP_KRATOS then
    return "goHeroA00"
  elseif character == pickupConsts.TAG_PICKUP_SON then
    return "goSon00"
  else
    assert(false, "'character' variable passed into PickupUtil:GetUICreatureGOName was not a proper pickup ID. It should either be pickupConsts.TAG_PICKUP_KRATOS or pickupConsts.TAG_PICKUP_SON. Value was: " .. tostring(character))
  end
end
local GetUICreature = function(character)
  local uiCreatureGOName = GetUICreatureGOName(character)
  return UI.FindCreatureByGOName(uiCreatureGOName)
end
local UpdateSlotOnUICreature = function(pickupSlotName, pickupName, pickupStage, creature, character)
  local uiCreatureGOName = GetUICreatureGOName(character)
  local uiCreature = UI.FindCreatureByGOName(uiCreatureGOName)
  local uiEquippedPickupName = GetPickupNameInSlot(uiCreature, pickupSlotName)
  if uiCreature ~= nil then
    if not IsValidName(pickupName) then
      if uiEquippedPickupName ~= nil then
        uiCreature:PickupRelinquishBySlot(pickupSlotName)
      end
    else
      local needAcquire = false
      if pickupName ~= uiEquippedPickupName then
        needAcquire = true
      else
        local uiStage = uiCreature:PickupGetStage(pickupName)
        if pickupStage ~= uiStage then
          needAcquire = true
        end
      end
      if needAcquire then
        uiCreature:PickupAcquire(pickupName, pickupStage)
      end
    end
  end
end
local ClearUISonPickups = function()
  local uiSon = GetUICreature(pickupConsts.TAG_PICKUP_SON)
  if uiSon == nil then
    return
  end
  local slotsToClear = {
    pickupConsts.Slot_PrimaryWeapon,
    pickupConsts.Slot_SecondaryWeapon
  }
  for i = 1, #slotsToClear do
    local currentSlot = slotsToClear[i]
    if GetPickupNameInSlot(uiSon, currentSlot) ~= nil then
      uiSon:PickupRelinquishBySlot(currentSlot)
    end
  end
end
local UpdateAllSlotsOnUICreature = function(creature, character)
  local pickupSlots = GetPickupSlotNames(character)
  for _, pickupSlotName in ipairs(pickupSlots) do
    local pickupName = GetPickupNameInSlot(creature, pickupSlotName)
    local pickupStage = GetStage(pickupName, creature)
    UpdateSlotOnUICreature(pickupSlotName, pickupName, pickupStage, creature, character)
  end
  for pickupSlotName in pairs(weaponUpgradeSlotNames[character]) do
    local upgradeSlots = GetWeaponUpgradeSlotNames(character, pickupSlotName)
    for _, upgradeSlotName in ipairs(upgradeSlots) do
      local upgradeName = GetPickupNameInSlot(creature, upgradeSlotName)
      local upgradeStage = GetStage(upgradeName, creature)
      UpdateSlotOnUICreature(upgradeSlotName, upgradeName, upgradeStage, creature, character)
    end
  end
end
local InitializeSlotsOnUICreatures = function()
  local Kratos = Player.FindPlayer()
  local Son = AI.FindSon()
  UpdateAllSlotsOnUICreature(Kratos, pickupConsts.TAG_PICKUP_KRATOS)
  if util.SonUI_ShouldShow() then
    UpdateAllSlotsOnUICreature(Son, pickupConsts.TAG_PICKUP_SON)
  end
end
local StreamSubList = function(character, subList, lastOutwardStream, maxOutwardStream, PrestreamListFunction)
  if subList and subList:get_active() then
    local buttonCount = subList:GetButtonCount()
    if not (0 < buttonCount) then
      goto lbl_65
    end
    local currIndex = subList._selectedButtonIndex
    local fullyStreamed = PrestreamListFunction(character, subList, currIndex)
    local maxI = 0
    if fullyStreamed then
      for i = 1, lastOutwardStream do
        local posIndex = (currIndex + i - 1) % buttonCount + 1
        local negIndex = (currIndex - i - 1) % buttonCount + 1
        fullyStreamed = PrestreamListFunction(character, subList, posIndex) and fullyStreamed
        fullyStreamed = PrestreamListFunction(character, subList, negIndex) and fullyStreamed
        maxI = i
        if not fullyStreamed then
          break
        end
      end
    end
    if fullyStreamed and lastOutwardStream < (buttonCount + 1) / 2 and lastOutwardStream < maxOutwardStream then
      lastOutwardStream = lastOutwardStream + 1
    elseif not fullyStreamed then
      lastOutwardStream = maxI
    end
  else
    lastOutwardStream = 0
  end
  ::lbl_65::
  return lastOutwardStream
end
local GetPickupGO = function(character, creature, pickupSlot)
  local pickupGO
  if character == pickupConsts.TAG_PICKUP_KRATOS or pickupSlot == "ArmorShield" then
    if pickupSlot == "WeaponComponent" or pickupSlot == "PrimaryWeapon" or pickupSlot == "WeaponSpecial_Light" or pickupSlot == "WeaponSpecial_Heavy" then
      pickupGO = creature.Axe
    elseif pickupSlot == "WeaponComponent_Blades" or pickupSlot == "Blades" or pickupSlot == "WeaponSpecial_Blades_Light" or pickupSlot == "WeaponSpecial_Blades_Heavy" then
      pickupGO = creature.Blades
    elseif pickupSlot == "ArmorShield" then
      pickupGO = creature:GetAttachmentGO("gokratosshield00")
    end
  elseif character == pickupConsts.TAG_PICKUP_SON and creature.GetAttachmentGO ~= nil then
    if pickupSlot == "PrimaryWeapon" then
      pickupGO = creature:GetAttachmentGO("gobow00")
    elseif pickupSlot == "SecondaryWeapon" then
      pickupGO = creature:GetAttachmentGO("goquiver00")
    end
  end
  if pickupGO == nil then
    pickupGO = creature:GetGameObject()
  end
  return pickupGO
end
return {
  IsValidSlotName = IsValidSlotName,
  GetPickupSlotNames = GetPickupSlotNames,
  GetWeaponUpgradeSlotNames = GetWeaponUpgradeSlotNames,
  GetPickupNameInSlot = GetPickupNameInSlot,
  GetSlotDisplayName = GetSlotDisplayName,
  GetSlotIcon = GetSlotIcon,
  GetSlotSpecialMeterDefaultColor = GetSlotSpecialMeterDefaultColor,
  GetSlotSpecialMeterCooldownColor = GetSlotSpecialMeterCooldownColor,
  GetWeaponSpecialSlots = GetWeaponSpecialSlots,
  WeaponSpecialSlotDisplayForWeapon = WeaponSpecialSlotDisplayForWeapon,
  WeaponSpecialSlotBelongsToWeapon = WeaponSpecialSlotBelongsToWeapon,
  GetAvailablePickupSlotNames = GetAvailablePickupSlotNames,
  Exists = Exists,
  IsValidName = IsValidName,
  GetDisplayName = GetDisplayName,
  GetDescription = GetDescription,
  GetEmptySlotDescription = GetEmptySlotDescription,
  GetIcon = GetIcon,
  GetRarityColor = GetRarityColor,
  HasTag = HasTag,
  HasSkillTree = HasSkillTree,
  GetSlotName = GetSlotName,
  IsInSlot = IsInSlot,
  GetProfileStage = GetProfileStage,
  GetStage = GetStage,
  GetMaxStage = GetMaxStage,
  GetStageDisplayName = GetStageDisplayName,
  GetTier = GetTier,
  GetLevel = GetLevel,
  GetCreatureFromCharacter = GetCreatureFromCharacter,
  GetCharacterFromCreature = GetCharacterFromCreature,
  IsWeaponSpecialSlot = IsWeaponSpecialSlot,
  IsPrimaryWeapon = IsPrimaryWeapon,
  IsWeapon = IsWeapon,
  IsArmor = IsArmor,
  IsWeaponSpecial = IsWeaponSpecial,
  IsWeaponComponent = IsWeaponComponent,
  IsBladesSpecialOrComponent = IsBladesSpecialOrComponent,
  IsNew = IsNew,
  IsEquipped = IsEquipped,
  GetRuneSocketCount = GetRuneSocketCount,
  GetRuneSocketCountPreview = GetRuneSocketCountPreview,
  GetAttribute = GetAttribute,
  GetPickupAttributes = GetPickupAttributes,
  HasPerks = HasPerks,
  PickupAcquire = PickupAcquire,
  PickupAcquireWhileOnCooldown = PickupAcquireWhileOnCooldown,
  IsUpgradeAllowed = IsUpgradeAllowed,
  ShouldUseMaterialSwap = ShouldUseMaterialSwap,
  CheckCharacterPickupID = CheckCharacterPickupID,
  GetUICreatureGOName = GetUICreatureGOName,
  GetUICreature = GetUICreature,
  UpdateSlotOnUICreature = UpdateSlotOnUICreature,
  InitializeSlotsOnUICreatures = InitializeSlotsOnUICreatures,
  ClearUISonPickups = ClearUISonPickups,
  StreamSubList = StreamSubList,
  GetPickupGO = GetPickupGO
}
