local tablex = require("core.tablex")
local animationUtil = require("ui.animationUtil")
local attributeUtil = require("ui.attributeUtil")
local colors = require("ui.colors")
local colorUtil = require("ui.colorUtil")
local consts = require("ui.consts")
local hooks = require("ui.hooks")
local hudConsts = require("ui.hudConsts")
local lamsConsts = require("ui.lamsConsts")
local meter = require("ui.meter")
local meterPreview = require("ui.meterPreview")
local pickupConsts = require("ui.pickupConsts")
local pickupUtil = require("ui.pickupUtil")
local resourceUtil = require("ui.resourceUtil")
local tutorialUtil = require("ui.tutorialUtil")
local util = require("ui.util")
local iconConsts = require("ui.iconConsts")
local AttributeCard = {}
local Audio = game.Audio
local GetTextHandle = util.GetTextHandle
local Pickup = game.Pickup
local Player = game.Player
local SetText = game.UI.SetText
local UI = game.UI
function AttributeCard.New(gameObjectReference)
  assert(gameObjectReference ~= nil)
  local newTable = {
    goGameObject = gameObjectReference,
    gameObjects = {},
    textHandles = {},
    textHandles_small = {},
    attributeMeterCount = #pickupConsts.Attributes,
    attributeMeters = {},
    attributeMeters_small = {},
    _descriptionsEnabled = false
  }
  local mt = {__index = AttributeCard}
  setmetatable(newTable, mt)
  return newTable
end
function AttributeCard:Init(state, isVendorCard)
  self._state = state
  self._hookTokens = {}
  self._isVendorCard = util.GetValueWithDefault(isVendorCard, false)
  local gameObjects = self.gameObjects
  local goRoot = self.goGameObject:FindSingleGOByName("Card")
  gameObjects.goRoot = goRoot
  gameObjects.goBlur = self.goGameObject:FindSingleGOByName("blur")
  gameObjects.goAttributes_Group = goRoot:FindSingleGOByName("Attributes_Group")
  gameObjects.goAttributes_Group_small = goRoot:FindSingleGOByName("Attributes_Group_small")
  gameObjects.goPowerLevelMeter = gameObjects.goAttributes_Group:FindSingleGOByName("powerLevelMeter")
  gameObjects.goPowerLevelMeter_small = gameObjects.goAttributes_Group_small:FindSingleGOByName("powerLevelMeter")
  gameObjects.goPowerLevelMeterNum = gameObjects.goPowerLevelMeter:FindSingleGOByName("powerLevel_Num")
  gameObjects.goPowerLevelMeterNum_small = gameObjects.goPowerLevelMeter_small:FindSingleGOByName("powerLevel_Num")
  gameObjects.goPowerLevelMeterFlourish = gameObjects.goPowerLevelMeter:FindSingleGOByName("flourish")
  gameObjects.goPowerLevelMeterFlourish_small = gameObjects.goPowerLevelMeter_small:FindSingleGOByName("flourish")
  gameObjects.goPowerLevelPreviewArrow = gameObjects.goAttributes_Group:FindSingleGOByName("powerLevelPreviewArrow")
  gameObjects.goPowerLevelPreviewArrow_small = gameObjects.goAttributes_Group_small:FindSingleGOByName("powerLevelPreviewArrow")
  self._show_small = false
  gameObjects.goAttributes_Group_small:Hide()
  gameObjects.goIconR = gameObjects.goAttributes_Group:FindSingleGOByName("icon_R")
  self.gameObjects.goIconR:Hide()
  self._currentlyVisible = false
  self._active = false
  local textHandles = self.textHandles
  local textHandles_small = self.textHandles_small
  local GetTextHandle = util.GetTextHandle
  textHandles.thLeftText = GetTextHandle(gameObjects.goAttributes_Group, "leftText")
  textHandles.thRightText = GetTextHandle(gameObjects.goAttributes_Group, "rightText")
  textHandles.thShowAttributeDesc = GetTextHandle(gameObjects.goAttributes_Group, "showAttributeDesc")
  textHandles.thPowerLevel = GetTextHandle(gameObjects.goPowerLevelMeterNum)
  UI.SetTextIsClickable(textHandles.thShowAttributeDesc)
  textHandles_small.thLeftText = GetTextHandle(gameObjects.goAttributes_Group_small, "leftText")
  textHandles_small.thRightText = GetTextHandle(gameObjects.goAttributes_Group_small, "rightText")
  textHandles_small.thShowAttributeDesc = GetTextHandle(gameObjects.goAttributes_Group_small, "showAttributeDesc")
  textHandles_small.thPowerLevel = GetTextHandle(gameObjects.goPowerLevelMeterNum_small)
  UI.SetTextIsClickable(textHandles_small.thShowAttributeDesc)
  UI.SetTextIsUIMacro(textHandles.thShowAttributeDesc)
  UI.SetTextIsUIMacro(textHandles_small.thShowAttributeDesc)
  gameObjects.meterRefnodes = {}
  gameObjects.meterRoots = {}
  textHandles.attributeDescriptions = {}
  textHandles.meterNames = {}
  textHandles.iconNames = {}
  gameObjects.meterRefnodes_small = {}
  gameObjects.meterRoots_small = {}
  textHandles_small.attributeDescriptions = {}
  textHandles_small.meterNames = {}
  textHandles_small.iconNames = {}
  for index, name in ipairs(pickupConsts.Attributes) do
    gameObjects.meterRefnodes[index] = gameObjects.goAttributes_Group:FindSingleGOByName("Attribute" .. tostring(index))
    gameObjects.meterRoots[index] = gameObjects.meterRefnodes[index]:FindSingleGOByName("attribute_bar")
    textHandles.meterNames[index] = GetTextHandle(gameObjects.meterRoots[index], "name")
    textHandles.iconNames[index] = GetTextHandle(gameObjects.meterRoots[index], "icon")
    assert(textHandles.meterNames[index] ~= nil, "Didn't get text handle in attribute card for attribute meterNames.")
    textHandles.attributeDescriptions[name] = GetTextHandle(gameObjects.goAttributes_Group, "AttributeDescription" .. tostring(index))
    assert(textHandles.attributeDescriptions[name] ~= nil, "Didn't get text handle in attribute card for attribute descriptions.")
    gameObjects.meterRefnodes_small[index] = gameObjects.goAttributes_Group_small:FindSingleGOByName("Attribute" .. tostring(index))
    gameObjects.meterRoots_small[index] = gameObjects.meterRefnodes_small[index]:FindSingleGOByName("attribute_bar")
    textHandles_small.meterNames[index] = GetTextHandle(gameObjects.meterRoots_small[index], "name")
    textHandles_small.iconNames[index] = GetTextHandle(gameObjects.meterRoots_small[index], "icon")
    assert(textHandles_small.meterNames[index] ~= nil, "Didn't get text handle in attribute card for attribute meterNames.")
    textHandles_small.attributeDescriptions[name] = GetTextHandle(gameObjects.goAttributes_Group_small, "AttributeDescription" .. tostring(index))
    assert(textHandles_small.attributeDescriptions[name] ~= nil, "Didn't get text handle in attribute card for attribute descriptions.")
  end
  self:SetupAttributeMeters(state)
  self.powerLevelMeter = meter.Meter.New(self, {
    Name = "power_level_meter",
    MeterObject = gameObjects.goPowerLevelMeter,
    MeterInstanceChildName = "powerLevel",
    FillAnimName = "powerLevel_Fill",
    FlourishAnimName = "powerLevel_Flourish",
    Percent = 0,
    TextHandle = textHandles.thPowerLevel,
    TextFormat = "%.0f"
  })
  self.powerLevelMeter_small = meter.Meter.New(self, {
    Name = "power_level_meter",
    MeterObject = gameObjects.goPowerLevelMeter_small,
    MeterInstanceChildName = "powerLevel",
    FillAnimName = "powerLevel_Fill",
    FlourishAnimName = "powerLevel_Flourish",
    Percent = 0,
    TextHandle = textHandles_small.thPowerLevel,
    TextFormat = "%.0f"
  })
  local showAll = true
  self:ShowCard(showAll)
  self:HideCard()
  SetText(self.textHandles.thPowerLevel, "")
  SetText(self.textHandles_small.thPowerLevel, "")
  self.gameObjects.goPowerLevelMeterFlourish:Hide()
  self.gameObjects.goPowerLevelMeterFlourish_small:Hide()
  self:DisableDescriptions()
end
function AttributeCard:SetupAttributeMeters(currState)
  currState.attributeMeters = {}
  currState.shared.AttributeName = {}
  currState.shared.AttributeDesc = {}
  local goAttributes_Group = self.gameObjects.goAttributes_Group
  for index, name in ipairs(pickupConsts.Attributes) do
    local goCurrentMeter = self.gameObjects.goAttributes_Group:FindSingleGOByName("Attribute" .. index)
    local goBaseMeterRefnode = goCurrentMeter:FindSingleGOByName("baseMeter")
    local goBaseMeterRoot = goBaseMeterRefnode:FindSingleGOByName("meter")
    local thBaseMeter = GetTextHandle(goBaseMeterRoot, "text")
    self.attributeMeters[index] = meterPreview.MeterPreview.New(currState, {
      Name = "Attribute" .. tostring(index),
      MeterObject = goCurrentMeter,
      MeterInstanceChildName = "attribute_bar",
      FillObjectName = "baseMeter",
      PreviewFillObjectName = "previewMeter",
      TextHandle = thBaseMeter,
      TextMaterial = "small_text",
      MaxValue = self:GetMax(name),
      TextFormat = "%.0f",
      TextIndex = index,
      SetColor = function(meter, color)
        self:SetMeterColor(meter, color)
      end,
      SetPreviewColor = function(meter, color)
        self:SetPreviewMeterColor(meter, color)
      end
    })
    self.attributeMeters[index]:Show()
    SetText(self.textHandles.meterNames[index], attributeUtil.GetDisplayName(name))
    SetText(self.textHandles.iconNames[index], iconConsts[name])
    local descriptionString = attributeUtil.GetDescription(name)
    SetText(self.textHandles.attributeDescriptions[name], descriptionString)
    goCurrentMeter = self.gameObjects.goAttributes_Group_small:FindSingleGOByName("Attribute" .. index)
    goBaseMeterRefnode = goCurrentMeter:FindSingleGOByName("baseMeter")
    goBaseMeterRoot = goBaseMeterRefnode:FindSingleGOByName("meter")
    thBaseMeter = GetTextHandle(goBaseMeterRoot, "text")
    self.attributeMeters_small[index] = meterPreview.MeterPreview.New(currState, {
      Name = "Attribute" .. tostring(index),
      MeterObject = goCurrentMeter,
      MeterInstanceChildName = "attribute_bar",
      FillObjectName = "baseMeter",
      PreviewFillObjectName = "previewMeter",
      TextHandle = thBaseMeter,
      TextMaterial = "small_text",
      MaxValue = self:GetMax(name),
      TextFormat = "%.0f",
      TextIndex = index,
      SetColor = function(meter, color)
        self:SetMeterColor(meter, color)
      end,
      SetPreviewColor = function(meter, color)
        self:SetPreviewMeterColor(meter, color)
      end
    })
    self.attributeMeters_small[index]:Show()
    SetText(self.textHandles_small.meterNames[index], attributeUtil.GetDisplayName(name))
    SetText(self.textHandles_small.iconNames[index], iconConsts[name])
    SetText(self.textHandles_small.attributeDescriptions[name], descriptionString)
  end
end
local g_creature
function AttributeCard:UpdateMeter_Equipped(equippedAttributes, character, creature)
  assert(equippedAttributes ~= nil and type(equippedAttributes) == "table", "Variable: attributes, passed into AttributeCard:UpdateMeter_Equipped was nil or not a table. Type is: " .. type(equippedAttributes))
  assert(#equippedAttributes <= pickupConsts.MaxHealthIndex, "Table with too many attributes were passed into AttributeCard")
  g_creature = creature
  for index, meter in ipairs(self.attributeMeters) do
    local currentValue = math.floor(equippedAttributes[index])
    local rate = 1
    meter:SetBaseValue(currentValue, rate)
  end
  for index, meter in ipairs(self.attributeMeters_small) do
    local currentValue = math.floor(equippedAttributes[index])
    local rate = 1
    meter:SetBaseValue(currentValue, rate)
  end
  self:UpdateGlobalInfoAttributes(character)
  if equippedAttributes[pickupConsts.PowerLevelIndex] == nil then
    equippedAttributes[pickupConsts.PowerLevelIndex] = creature:AttributeGetValue("PowerLevel")
  end
  self:UpdatePowerLevel_Equipped(equippedAttributes[pickupConsts.PowerLevelIndex])
  if equippedAttributes[pickupConsts.MaxHealthIndex] == nil then
    equippedAttributes[pickupConsts.MaxHealthIndex] = util.Round(creature:MeterGetMax(hudConsts.METER_HEALTH))
  end
  self:UpdateHP(character, equippedAttributes[pickupConsts.MaxHealthIndex])
end
function AttributeCard:UpdateMeter_Preview(attributes)
  local rate = 1
  if attributes ~= nil then
    assert(type(attributes) == "table", "Variable: attributes, passed into AttributeCard:UpdateMeter_Preview was nil or not a table.")
    assert(#attributes <= self.attributeMeterCount, "Table with too many attributes were passed into AttributeCard")
    for index, meter in ipairs(self.attributeMeters) do
      local previewValue = math.floor(attributes[index])
      meter:SetPreviewValue(previewValue, rate)
      meter:EnablePreview()
    end
    for index, meter in ipairs(self.attributeMeters_small) do
      local previewValue = math.floor(attributes[index])
      meter:SetPreviewValue(previewValue, rate)
      meter:EnablePreview()
    end
  else
    for _, meter in ipairs(self.attributeMeters) do
      meter:DisablePreview()
    end
    for _, meter in ipairs(self.attributeMeters_small) do
      meter:DisablePreview()
    end
  end
  local creature = g_creature
  if creature then
    local powerLevel = creature:AttributeGetValue("PowerLevel")
    self:UpdatePowerLevel_Preview(powerLevel)
  end
end
function AttributeCard:ToggleDescriptions()
  if self._show_small then
    return
  end
  if self._descriptionsEnabled then
    self:DisableDescriptions()
    Audio.PlaySound("SND_UX_Menu_Nav_Drop_Down_Contract")
  else
    self:EnableDescriptions()
    Audio.PlaySound("SND_UX_Menu_Nav_Drop_Down_Expand")
  end
end
function AttributeCard:SmallCard(on)
  if not self._currentlyVisible then
    return
  end
  self._show_small = on
  if self._show_small then
    self.gameObjects.goAttributes_Group:Hide()
    self.gameObjects.goAttributes_Group_small:Show()
  else
    self.gameObjects.goAttributes_Group:Show()
    self.gameObjects.goAttributes_Group_small:Hide()
  end
end
function AttributeCard:EnableDescriptions()
  self._descriptionsEnabled = true
  local startFrame = 0
  local endFrame = 1
  local rate = 3
  UI.Anim(self.gameObjects.goAttributes_Group, consts.AS_Forward, "", rate, startFrame, endFrame)
  UI.SetText(util.GetTextHandle(self.gameObjects.goAttributes_Group, "showAttributeDesc"), util.GetLAMSMsg(lamsConsts.HideAttributeDescriptions))
end
function AttributeCard:DisableDescriptions()
  self._descriptionsEnabled = false
  local startFrame = 1
  local endFrame = 0
  local rate = 3
  UI.Anim(self.gameObjects.goAttributes_Group, consts.AS_Reverse, "", rate, startFrame, endFrame)
  UI.SetText(util.GetTextHandle(self.gameObjects.goAttributes_Group, "showAttributeDesc"), util.GetLAMSMsg(lamsConsts.ShowAttributeDescriptions))
end
function AttributeCard:UpdateHP(character, maxHp)
  local inGameCreature = pickupUtil.GetCreatureFromCharacter(character)
  local currentHp = util.Round(inGameCreature:MeterGetValue(hudConsts.METER_HEALTH))
  currentHp = math.min(maxHp, currentHp)
  SetText(self.textHandles.thLeftText, util.GetLAMSMsg(lamsConsts.HP) .. " " .. tostring(currentHp) .. " / " .. tostring(maxHp))
  SetText(self.textHandles_small.thLeftText, util.GetLAMSMsg(lamsConsts.HP) .. " " .. tostring(currentHp) .. " / " .. tostring(maxHp))
end
function AttributeCard:UpdateResurrectionStone()
  local kratos = pickupUtil.GetCreatureFromCharacter(pickupConsts.TAG_PICKUP_KRATOS)
  local valueA = game.Wallets.GetResourceValue("HERO", "ResurrectionRuneStoneA")
  local valueB = game.Wallets.GetResourceValue("HERO", "ResurrectionRuneStoneB")
  local valueC = game.Wallets.GetResourceValue("HERO", "ResurrectionRuneStoneC")
  local shown = -1 < valueA or -1 < valueB or -1 < valueC
  local on = 0 < valueA or 0 < valueB or 0 < valueC
  if not shown then
    self.gameObjects.goIconR:Hide()
    return
  else
    self.gameObjects.goIconR:Show()
  end
  local blend
  local color = colors.RES_EMPTY
  if on then
    if 0 < valueA then
      color = colors.RES_A
    elseif 0 < valueB then
      color = colors.RES_B
    elseif 0 < valueC then
      color = colors.RES_C
    end
    blend = 100
  else
    blend = 0
  end
  self.gameObjects.goIconR:GetMaterialEntry("SonResStone", "Equipped.cst_AlphaBlendAmount").Value = blend
  util.SetGameObjectColor(self.gameObjects.goIconR, color, "SonResStone", "Equipped", "cst_EmissiveTint")
end
function AttributeCard:UpdateRage(creature)
  local textHandles = self.textHandles
  local rageSegments = creature:MeterGetMax(hudConsts.METER_BLOOD) / creature:MeterGetSegmentSize(hudConsts.METER_BLOOD)
  rageSegments = math.floor(rageSegments)
  SetText(textHandles.thRightText, util.GetLAMSMsg(lamsConsts.RAGE) .. " " .. tostring(rageSegments))
  self.gameObjects.goIconR:SetMaterialSwap("Rage")
end
function AttributeCard:UpdateArrowCount(creature)
  local textHandles = self.textHandles
  local arrowCount = creature:MeterGetMax(hudConsts.METER_ARROWS) / creature:MeterGetSegmentSize(hudConsts.METER_ARROWS)
  SetText(textHandles.thRightText, tostring(arrowCount) .. " ARROWS")
  self.gameObjects.goIconR:SetMaterialSwap("Arrow")
end
function AttributeCard:UpdatePowerLevel_Equipped(powerLevel)
  self.gameObjects.goPowerLevelMeterFlourish:Hide()
  self.gameObjects.goPowerLevelMeterFlourish_small:Hide()
  if self._prevPowerLevel ~= nil and self._prevPowerLevel ~= powerLevel or not self._firstPowerLevelSet then
    if not self._firstPowerLevelSet then
      self:UpdatePowerLevel_Internal(powerLevel)
    else
      local delay = 0.3
      local timerName = "PowerLevelFlourishDelay"
      if self._state:HaveTimer(timerName) then
        self._state:StopTimer(timerName)
      end
      self._state:StartTimer(timerName, delay, function()
        self:UpdatePowerLevel_Internal(powerLevel)
      end)
      local animName = ""
      local animRate = 1
      local animPos_Start = 0
      local animPos_End = 1
      UI.Anim(self.gameObjects.goPowerLevelMeterFlourish, consts.AS_Forward, animName, animRate, animPos_Start, animPos_End)
      UI.Anim(self.gameObjects.goPowerLevelMeterFlourish_small, consts.AS_Forward, animName, animRate, animPos_Start, animPos_End)
    end
  end
  self._prevPowerLevel = powerLevel
end
function AttributeCard:UpdatePowerLevel_Preview(previewValue)
  if self._prevPowerLevel ~= nil then
    local goArrow = self.gameObjects.goPowerLevelPreviewArrow
    local goArrow_small = self.gameObjects.goPowerLevelPreviewArrow_small
    goArrow:Show()
    goArrow_small:Show()
    local diff = util.Round((previewValue - self._prevPowerLevel) * 100)
    if 0 < diff then
      goArrow:SetMaterialSwap("UpgradeArrow_Up")
      goArrow_small:SetMaterialSwap("UpgradeArrow_Up")
    elseif diff < 0 then
      goArrow:SetMaterialSwap("UpgradeArrow_Down")
      goArrow_small:SetMaterialSwap("UpgradeArrow_Down")
    else
      goArrow:Hide()
      goArrow_small:Hide()
    end
  end
end
function AttributeCard:ClearPowerLevelPreview()
  self.gameObjects.goPowerLevelPreviewArrow:Hide()
  self.gameObjects.goPowerLevelPreviewArrow_small:Hide()
end
local powerLevelNumberOffsets = {
  [4] = {0, 0.117},
  [10] = {-0.1, 0}
}
local previewArrowOffsets = {
  [10] = {4.2, -0.479}
}
function AttributeCard:UpdatePowerLevel_Internal(powerLevel)
  local integerPowerLevel = util.Truncate(powerLevel)
  local newMin = 0
  local newMax = 1
  local newValue = 0
  local powerLevelStyle = "RuneCardLevel"
  local powerLevelText = ""
  local powerLevelNumberOffsetIndex = integerPowerLevel
  if powerLevel < 1 then
    self.powerLevelMeter:SetRange(newMin, newMax, newValue)
    self.powerLevelMeter_small:SetRange(newMin, newMax, newValue)
    powerLevelText = util.StyleText(tostring(1), powerLevelStyle)
  else
    newMin = integerPowerLevel
    newMax = integerPowerLevel + 1
    newValue = powerLevel
    self.powerLevelMeter:SetRange(newMin, newMax, newValue)
    self.powerLevelMeter_small:SetRange(newMin, newMax, newValue)
    if 10 <= integerPowerLevel then
      powerLevelStyle = "RuneCardLevel_DoubleDigits"
      powerLevelNumberOffsetIndex = 10
    end
    powerLevelText = util.StyleText(tostring(integerPowerLevel), powerLevelStyle)
  end
  SetText(self.textHandles.thPowerLevel, powerLevelText)
  SetText(self.textHandles_small.thPowerLevel, powerLevelText)
  local xOffset = powerLevelNumberOffsets[powerLevelNumberOffsetIndex] and powerLevelNumberOffsets[powerLevelNumberOffsetIndex][1] or 0.074
  local yOffset = powerLevelNumberOffsets[powerLevelNumberOffsetIndex] and powerLevelNumberOffsets[powerLevelNumberOffsetIndex][2] or 0.117
  local vTargetPos = engine.Vector.New(xOffset, yOffset, 0)
  local useWorldSpace = false
  UI.SetGOTransformInterpolated(self.gameObjects.goPowerLevelMeterNum, vTargetPos, 0, useWorldSpace)
  UI.SetGOTransformInterpolated(self.gameObjects.goPowerLevelMeterNum_small, vTargetPos, 0, useWorldSpace)
  xOffset = previewArrowOffsets[powerLevelNumberOffsetIndex] ~= nil and previewArrowOffsets[powerLevelNumberOffsetIndex][1] or 4.052
  yOffset = previewArrowOffsets[powerLevelNumberOffsetIndex] ~= nil and previewArrowOffsets[powerLevelNumberOffsetIndex][2] or -0.479
  vTargetPos = engine.Vector.New(xOffset, yOffset, 0)
  UI.SetGOTransformInterpolated(self.gameObjects.goPowerLevelPreviewArrow, vTargetPos, 0, useWorldSpace)
  UI.SetGOTransformInterpolated(self.gameObjects.goPowerLevelPreviewArrow_small, vTargetPos, 0, useWorldSpace)
  self._firstPowerLevelSet = true
end
function AttributeCard:UpdateGlobalInfoAttributes(character)
  pickupUtil.CheckCharacterPickupID(character)
  local creature = self._isVendorCard and pickupUtil.GetCreatureFromCharacter(character) or pickupUtil.GetUICreature(character)
  if character == pickupConsts.TAG_PICKUP_KRATOS then
    self:UpdateResurrectionStone(creature)
  else
    self:UpdateArrowCount(creature)
  end
end
function AttributeCard:GetMax(attributeName)
  local max = pickupConsts.MaxAttributeValues[attributeName]
  assert(max ~= nil, "Max value for attribute was nil")
  return max
end
function AttributeCard:SetMeterColor(meter, color)
  local goObjToColor = meter:GetInstancedFillObject()
  util.SetGameObjectColor(goObjToColor, color, "statBar_Fill", "Layer0", "cst_EmissiveTint")
end
function AttributeCard:SetPreviewMeterColor(meter, color)
  local goObjToColor = meter:GetInstancedPreviewFillObject()
  util.SetGameObjectColor(goObjToColor, color, "statBar_Fill", "Layer0", "cst_EmissiveTint")
end
function AttributeCard:ShowCard(showAll)
  if showAll then
    for _, obj in pairs(self.gameObjects) do
      if type(obj) == "table" then
        self:ShowCard_Recursive(obj)
      else
        obj:Show()
      end
    end
  else
    self.goGameObject:Show()
    self.gameObjects.goAttributes_Group:Show()
    self.gameObjects.goAttributes_Group_small:Hide()
    local fadeAlpha = 1
    local time = 0.3
    UI.AlphaFade(self.gameObjects.goAttributes_Group, fadeAlpha, time)
  end
  self:UpdateResurrectionStone()
  self.powerLevelMeter:Show()
  self.powerLevelMeter_small:Show()
  if not self._currentlyVisible then
    self._currentlyVisible = true
    self._active = true
    util.InstallEventHooks(hooks, self, {
      "EVT_L3_Release"
    }, function(attributeCard)
      tutorialUtil.HandleEvent(attributeCard, {
        "EVT_L3_Release"
      }, function()
        attributeCard:ToggleDescriptions()
      end)
    end)
  end
end
function AttributeCard:ShowCard_Recursive(obj)
  if type(obj) == "table" then
    for _, childObj in pairs(obj) do
      self:ShowCard_Recursive(childObj)
    end
  else
    obj:Show()
  end
end
function AttributeCard:HideCard(instant)
  if self._currentlyVisible then
    self._currentlyVisible = false
    self._active = false
    if instant then
      self.gameObjects.goAttributes_Group:Hide()
    end
    self.gameObjects.goAttributes_Group_small:Hide()
    local fadeAlpha = 0
    local time = 0.3
    UI.AlphaFade(self.gameObjects.goAttributes_Group, fadeAlpha, time)
    util.UninstallEventHooks(hooks, self, {
      "EVT_L3_Release"
    })
    self._hookTokens = {}
    self.powerLevelMeter:Show()
    self.powerLevelMeter_small:Show()
  end
end
function AttributeCard:get_active()
  return self._active
end
return {AttributeCard = AttributeCard}
