local tablex = require("core.tablex")
local clone = require("core.clone")
local animationUtil = require("ui.animationUtil")
local characterUtil = require("ui.characterUtil")
local colors = require("ui.colors")
local consts = require("ui.consts")
local exchangeCard = require("ui.exchangeCard")
local gemInfoCard = require("ui.gemInfoCard")
local iconConsts = require("ui.iconConsts")
local lamsConsts = require("ui.lamsConsts")
local pickupConsts = require("ui.pickupConsts")
local pickupUtil = require("ui.pickupUtil")
local recipeUtil = require("ui.recipeUtil")
local resourceConsts = require("ui.resourceConsts")
local resourceUtil = require("ui.resourceUtil")
local runeUtil = require("ui.runeUtil")
local skillTreeConsts = require("ui.skillTreeConsts")
local sliderHoldFill = require("ui.sliderHoldFill")
local statsCard = require("ui.statsCard")
local tutorialUtil = require("ui.tutorialUtil")
local util = require("ui.util")
local Audio = game.Audio
local UI = game.UI
local Resources = game.Resources
local Wallets = game.Wallets
local CardManager = {}
function CardManager.New(state, gameObjectReference)
  assert(state ~= nil, "State entered into CardManager constructor was nil.")
  assert(gameObjectReference ~= nil, "GameObject reference entered into CardManager constructor was nil.")
  local newTable = {
    _state = state,
    _gameObject = gameObjectReference,
    _isVendor = false,
    _isComparisonCardShowing = false,
    _toggleState = false,
    _requirementsCardBodyOn = false,
    _cantBuySpecialCase = false,
    statsCard = nil,
    comparisonCard = nil,
    exchangeCard = nil,
    holdFill = nil,
    children = {},
    textHandles = {}
  }
  local mt = {__index = CardManager}
  setmetatable(newTable, mt)
  return newTable
end
function CardManager:Init(isVendor, args)
  self._isVendor = isVendor
  self.children.goStatsCard = self._gameObject:FindSingleGOByName("StatsCard")
  self.children.goComparisonCard = self._gameObject:FindSingleGOByName("StatsCard_Compare")
  local nonCompareArgs = args
  local compareArgs = args
  if nonCompareArgs == nil then
    nonCompareArgs = {}
  else
    nonCompareArgs = clone.deep(args)
  end
  if compareArgs == nil then
    compareArgs = {}
  else
    compareArgs = clone.deep(args)
  end
  self.statsCard = statsCard.StatsCard.New(self.children.goStatsCard)
  self.comparisonCard = statsCard.StatsCard.New(self.children.goComparisonCard)
  nonCompareArgs.ComparisonCard = self.comparisonCard
  compareArgs.NonComparisonCard = self.statsCard
  self.statsCard:Init(isVendor, false, nonCompareArgs)
  self.comparisonCard:Init(isVendor, true, compareArgs)
  self.comparisonCard:SetButtonStates(nil, nil)
  self.children.goExchangeCard = self._gameObject:FindSingleGOByName("exchange_card")
  self.exchangeCard = exchangeCard.ExchangeCard.New(self._state, self.children.goExchangeCard)
  self.exchangeCard:Init()
  local goGemInfoCard = util.GetUiObjByName("Weapon_Gem_Info_Card")
  self.gemInfoCard = gemInfoCard.GemInfoCard.New(self, goGemInfoCard)
  self.gemInfoCard:Init(self, isVendor)
  self.children.goSliderCraft = self._gameObject:FindSingleGOByName("slider_craft")
  self.holdFill = sliderHoldFill.SliderHoldFill.New(self._state, {
    Name = "CardManager_HoldFillMeter",
    SliderObject = self.children.goSliderCraft,
    HoldStartSound = "SND_UX_Vendor_Upgrade_Hold_Button_Start",
    HoldSound = "SND_UX_Vendor_Upgrade_Hold_X",
    SuccessSound = "SND_UX_Vendor_Upgrade_Hold_X_Success",
    StopSound = "SND_UX_Vendor_Upgrade_Hold_Reset_LP",
    StopWhenFull = true,
    IncAnimRate = 1,
    DecAnimRate = 0.4,
    PressEvent = "EVT_Square_Press",
    ReleaseEvent = "EVT_Square_Release"
  })
  self.children.goItemInfo = self._gameObject:FindSingleGOByName("ItemInfo")
  self.children.goBlur = self._gameObject:FindSingleGOByName("vendor_stave_blur")
  self.children.goLeftCardParent = self._gameObject:FindSingleGOByName("LeftCardParent")
  self.children.goRecipeHeader = self.children.goLeftCardParent:FindSingleGOByName("RecipeHeader")
  self.textHandles.thRecipeHeader = util.GetTextHandle(self.children.goRecipeHeader, "text_RecipeHeader")
  self.children.goRequirementsBoxGroup = {}
  self.textHandles.thRequirementsBoxGroup = {}
  self.children.goRequirementsBoxGroup.goRequirementsBox = self._gameObject:FindSingleGOByName("RequirementsBox")
  self.children.goRequirementsBoxGroup.goRequirementsGroup = self._gameObject:FindSingleGOByName("RequirementsGroup")
  self.children.goRequirementsBoxGroup.goRequirementsFooter = self._gameObject:FindSingleGOByName("RequirementsFooter")
  self.children.goRequirementsBoxGroup.goRequirementsUnavailableBacking = self.children.goSliderCraft:FindSingleGOByName("unavailable")
  self.children.goRequirementsBoxGroup.goCraftTextPrompt = self._gameObject:FindSingleGOByName("CraftTextPrompt")
  self.textHandles.thRequirementsBoxGroup.thRequirementsHeader = util.GetTextHandle(self.children.goRequirementsBoxGroup.goRequirementsBox, "text_RequirementsHeader")
  self.textHandles.thRequirementsBoxGroup.thCraftText = util.GetTextHandle(self.children.goRequirementsBoxGroup.goCraftTextPrompt)
  UI.SetTextIsClickable(self.textHandles.thRequirementsBoxGroup.thCraftText)
  self.children.goRequirementsBoxGroup.goInputs = {}
  self.textHandles.thRequirementsBoxGroup.thInputs = {}
  for inputIndex = 1, resourceConsts.RECIPE_MAX_INPUTS do
    local goInputTable = {}
    local thInputTable = {}
    goInputTable.goResourceRow = self.children.goRequirementsBoxGroup.goRequirementsBox:FindSingleGOByName("RecipeResource" .. inputIndex)
    goInputTable.goRoot = goInputTable.goResourceRow:FindSingleGOByName("Root")
    goInputTable.goResourceProgressBar = goInputTable.goRoot:FindSingleGOByName("attribute_meter_resource")
    goInputTable.goResourceProgressBarChild = goInputTable.goResourceProgressBar:FindSingleGOByName("meter")
    thInputTable.thRecipeResource = util.GetTextHandle(goInputTable.goRoot, "text_name")
    thInputTable.thRecipeResource_Icon = util.GetTextHandle(goInputTable.goRoot, "text_icon")
    thInputTable.thRecipeResource_Amount = util.GetTextHandle(goInputTable.goRoot, "text_amount")
    self.children.goRequirementsBoxGroup.goInputs[inputIndex] = goInputTable
    self.textHandles.thRequirementsBoxGroup.thInputs[inputIndex] = thInputTable
  end
  if isVendor then
    UI.SetUIGORenderLayer(self._gameObject, consts.RenderLayer_World)
    UI.SetUIGORenderLayer(self.children.goStatsCard, consts.RenderLayer_World)
    UI.SetUIGORenderLayer(self.children.goComparisonCard, consts.RenderLayer_World)
    UI.SetUIGORenderLayer(self.children.goExchangeCard, consts.RenderLayer_World)
  else
    UI.SetUIGORenderLayer(self._gameObject, consts.RenderLayer_WorldUI)
    UI.SetUIGORenderLayer(self.children.goStatsCard, consts.RenderLayer_WorldUI)
    UI.SetUIGORenderLayer(self.children.goComparisonCard, consts.RenderLayer_WorldUI)
    UI.SetUIGORenderLayer(self.children.goExchangeCard, consts.RenderLayer_WorldUI)
  end
  self._gameObject:Hide()
  local prefix = isVendor and "Vendor_" or "Resources_"
  tutorialUtil.RegisterRootDesaturationObject(prefix .. "Stave_Group", self._gameObject)
  tutorialUtil.RegisterDesaturationObject(prefix .. "StatsCard", self.children.goStatsCard)
  tutorialUtil.RegisterDesaturationObject(prefix .. "StatsCard_Compare", self.children.goComparisonCard)
  tutorialUtil.RegisterDesaturationObject(prefix .. "ExchangeCard", self.children.goExchangeCard)
  tutorialUtil.RegisterDesaturationObject(prefix .. "RequirementsBox", self.children.goRequirementsBoxGroup.goRequirementsBox)
  tutorialUtil.RegisterDesaturationObject(prefix .. "StatsCard_IconGroup", self.statsCard.children.goIconGroup)
  local goStatsCardAttributeStat1 = self.statsCard.children.goAttributesGroup:FindSingleGOByName("Stat1")
  tutorialUtil.RegisterDesaturationObject(prefix .. "StatsCard_Stat1", goStatsCardAttributeStat1)
end
function CardManager:IsToggleActive()
  return self._toggleState
end
function CardManager:ShowRootLevelGOs()
  self._gameObject:Show()
  self.children.goLeftCardParent:Show()
  self.children.goItemInfo:Show()
  self.children.goBlur:Show()
  self.children.goRecipeHeader:Show()
end
function CardManager:HideRootLevelGOs()
  self._gameObject:Hide()
  self.children.goLeftCardParent:Hide()
  self.children.goItemInfo:Hide()
  self.children.goRecipeHeader:Hide()
  self.children.goBlur:Hide()
end
function CardManager:HideAll()
  self.statsCard:HideCard()
  self.comparisonCard:HideCard()
  self._state:SendEventToUIFsm("vendorMenu", "EVT_LARGE_ATTRIBUTE_CARD")
  self.exchangeCard:HideCard()
  self.gemInfoCard:HideCard()
  self:HideRootLevelGOs()
  self:HideRequirementsBoxGroup()
  self:UpdateRequirementsBoxGroup(nil, false, nil)
  self.holdFill:OnSliderParentHide()
end
function CardManager:DisplayCard_ForRecipe(recipeListItem, canRecipeBeMade, subStateIndex, character, canCompare)
  local recipeName = recipeUtil.RecipeListItem_GetRecipeName(recipeListItem)
  self:ShowRootLevelGOs()
  self:ShowRequirementsBoxGroup(recipeName, canRecipeBeMade)
  self:UpdateRequirementsBoxGroup(recipeListItem, canRecipeBeMade, subStateIndex)
  animationUtil.DoDefaultTransitionAnim(self.children.goLeftCardParent)
  if not self._isComparisonCardShowing then
    self.comparisonCard:HideCard()
    self._state:SendEventToUIFsm("vendorMenu", "EVT_LARGE_ATTRIBUTE_CARD")
  end
  local showAll = false
  local shouldUpdateAttributes = recipeUtil.RecipeListItem_ShouldUpdateAttributes(recipeListItem)
  local isSellRecipe = recipeUtil.RecipeIsForSell(recipeName)
  local isArtifactRecipe = recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_ARTIFACT)
  local isResurrectionStoneRecipe = recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_RESURRECTION_STONE)
  local isRuneRecipe = recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_RUNE)
  local isRunicAttackRecipe = recipeUtil.RecipeIsForRunicAttack(recipeName)
  local isSellRuneRecipe = isSellRecipe and isRuneRecipe
  local primaryRecipeItem = recipeUtil.RecipeListItem_GetPrimaryItem(recipeListItem)
  local primaryItemType = isSellRuneRecipe and resourceConsts.RESOURCE_FLAG_RUNE or recipeUtil.GetRecipeItemType(primaryRecipeItem)
  local isResourceRecipe = primaryItemType == resourceConsts.RESOURCE_FLAG_RESOURCE and not recipeUtil.IsReinforcementRecipe(recipeName)
  local useExchangeCard = isArtifactRecipe or isResourceRecipe and not isResurrectionStoneRecipe and not isRuneRecipe and not isRunicAttackRecipe
  local cardHeight
  if useExchangeCard then
    self.statsCard:HideCard()
    self.exchangeCard:ClearCard()
    self.exchangeCard:ShowCard(showAll)
    self.exchangeCard:SetItem(recipeListItem, resourceConsts.RESOURCE_FLAG_RECIPE)
    cardHeight = self.exchangeCard:GetCardHeight()
  else
    self.exchangeCard:HideCard()
    self.statsCard:ClearCard()
    self.statsCard:ShowCard(showAll)
    self.gemInfoCard:HideCard()
    if isRunicAttackRecipe then
      local primaryItemName = recipeUtil.GetRecipeItemName(primaryRecipeItem)
      self.gemInfoCard:SetGem(primaryItemName, true)
      cardHeight = 28.1
      self.gemInfoCard:ShowCard(false, true)
      self.statsCard:HideCard()
    elseif isSellRuneRecipe then
      local runeInfo = primaryRecipeItem
      local itemType = resourceConsts.RESOURCE_FLAG_RUNE
      local character = pickupConsts.TAG_PICKUP_KRATOS
      local itemIsEquipped
      self.statsCard:SetItem(runeInfo, itemType, character, itemIsEquipped)
    elseif isResourceRecipe then
      local primaryItemName = recipeUtil.GetRecipeItemName(primaryRecipeItem)
      local character = pickupConsts.TAG_PICKUP_KRATOS
      local itemIsEquipped
      self.statsCard:SetItem(primaryItemName, primaryItemType, character, itemIsEquipped)
    else
      local itemType = resourceConsts.RESOURCE_FLAG_RECIPE
      local itemIsEquipped
      self.statsCard:SetItem(recipeListItem, itemType, character, itemIsEquipped)
    end
    local leftButtonMsg, rightButtonMsg
    if canCompare == true then
      rightButtonMsg = "[R3]" .. util.GetLAMSMsg(lamsConsts.Compare)
    end
    self.statsCard:SetButtonStates(leftButtonMsg, rightButtonMsg)
  end
  self:UpdateRecipeCardHeights(cardHeight)
end
function CardManager:UpdateRecipeCardHeights(height)
  if height == nil then
    height = self.exchangeCard:IsShowing() and self.exchangeCard:GetCardHeight() or self.statsCard:GetCardHeight()
  end
  self:UpdateBackingHeight(height)
  self:UpdateRequirementsBoxPosition(height)
end
function CardManager:DisplayCard_ForLostItem(lostItem)
  self:ShowRootLevelGOs()
  self.children.goRecipeHeader:Hide()
  self:HideRequirementsBoxGroup()
  self.comparisonCard:HideCard()
  self._state:SendEventToUIFsm("vendorMenu", "EVT_LARGE_ATTRIBUTE_CARD")
  local showAll = false
  local itemName = lostItem.Name
  local itemType = lostItem.Type
  local character = pickupConsts.TAG_PICKUP_KRATOS
  local itemIsEquipped = false
  if itemType == nil then
    self.gemInfoCard:HideCard()
    self.exchangeCard:HideCard()
    self.statsCard:HideCard()
    self.statsCard:SetButtonStates(nil, nil)
    return
  end
  if itemType == resourceConsts.RESOURCE_FLAG_RUNE then
    self.gemInfoCard:HideCard()
    self.exchangeCard:HideCard()
    self.statsCard:ClearCard()
    self.statsCard:ShowCard(showAll)
    local runeInfo = game.Wallets.GetRuneInfo(resourceConsts.WALLET_LOST_ITEMS, itemName)
    self.statsCard:SetItem(runeInfo, itemType, character, itemIsEquipped)
  elseif itemType == resourceConsts.RESOURCE_FLAG_RESOURCE then
    local isRunicAttack = false
    for i = 1, #resourceConsts.RUNIC_ATTACK_FLAGS do
      if Resources.HasFlag(itemName, resourceConsts.RUNIC_ATTACK_FLAGS[i]) then
        isRunicAttack = true
        break
      end
    end
    self.statsCard:HideCard()
    if isRunicAttack then
      self.exchangeCard:HideCard()
      self.gemInfoCard:SetGem(itemName)
      self.gemInfoCard:ShowCard(false, true)
    else
      self.gemInfoCard:HideCard()
      self.exchangeCard:ClearCard()
      self.exchangeCard:ShowCard(showAll)
      self.exchangeCard:SetItem(itemName, resourceConsts.RESOURCE_FLAG_RESOURCE)
      self.exchangeCard:SetAmount(Wallets.GetResourceValue(resourceConsts.WALLET_LOST_ITEMS, itemName))
    end
  else
    self.gemInfoCard:HideCard()
    self.exchangeCard:HideCard()
    self.statsCard:ClearCard()
    self.statsCard:ShowCard(showAll)
    self.statsCard:SetItem(itemName, itemType, character, itemIsEquipped)
  end
  self.statsCard:SetButtonStates(nil, nil)
end
function CardManager:ShowComparisonCard(itemName, itemType, character, itemIsEquipped, args)
  self._isComparisonCardShowing = true
  self.comparisonCard:ClearCard()
  self.comparisonCard:ShowCard()
  self._state:SendEventToUIFsm("vendorMenu", "EVT_SMALL_ATTRIBUTE_CARD")
  self.comparisonCard:SetItem(itemName, itemType, character, itemIsEquipped, args)
  self:UpdateRecipeCardHeights()
end
function CardManager:HideComparisonCard()
  self._isComparisonCardShowing = false
  self.comparisonCard:ClearCard()
  self.comparisonCard:HideCard()
  self._state:SendEventToUIFsm("vendorMenu", "EVT_LARGE_ATTRIBUTE_CARD")
  self:UpdateRecipeCardHeights()
end
function CardManager:ToggleComparisonCard(itemName, itemType, character, itemIsEquipped, args)
  self._toggleState = not self._toggleState
  if self._isComparisonCardShowing then
    Audio.PlaySound("SND_UX_Pause_Menu_Compare_Hide")
    self:HideComparisonCard()
  else
    Audio.PlaySound("SND_UX_Pause_Menu_Compare_Show")
    self:ShowComparisonCard(itemName, itemType, character, itemIsEquipped, args)
  end
end
function CardManager:ForceToggleOff()
  self._toggleState = false
  self:HideComparisonCard()
end
function CardManager:ShowRequirementsBoxGroup()
  self.children.goRequirementsBoxGroup.goRequirementsBox:Show()
  self.children.goRequirementsBoxGroup.goRequirementsGroup:Show()
  self.children.goRequirementsBoxGroup.goRequirementsFooter:Show()
  for _, inputTable in ipairs(self.children.goRequirementsBoxGroup.goInputs) do
    inputTable.goResourceRow:Show()
    inputTable.goRoot:Show()
    inputTable.goResourceProgressBar:Hide()
    inputTable.goResourceProgressBarChild:Hide()
  end
end
function CardManager:HideRequirementsBoxGroup()
  self.children.goRequirementsBoxGroup.goRequirementsBox:Hide()
  self.children.goRequirementsBoxGroup.goRequirementsGroup:Hide()
  self.children.goRequirementsBoxGroup.goRequirementsFooter:Hide()
  for _, inputTable in ipairs(self.children.goRequirementsBoxGroup.goInputs) do
    inputTable.goResourceRow:Hide()
    inputTable.goRoot:Hide()
    inputTable.goResourceProgressBar:Hide()
    inputTable.goResourceProgressBarChild:Hide()
  end
end
function CardManager:UpdateRequirementsBoxGroup(recipeListItem, canRecipeBeMade, subStateIndex)
  self:ResetRecipeResources()
  self:UpdateHoldFill(recipeListItem, canRecipeBeMade, subStateIndex)
  self:UpdateRecipeResources(recipeListItem, canRecipeBeMade)
end
function CardManager:UpdateBackingHeight(cardHeight)
  local requirementsCardHeight_Header = 3
  local requirementsCardHeight_Body = 6
  local requirementsCardHeight_Footer = 2
  local totalBackingHeight = cardHeight + requirementsCardHeight_Header
  if self._requirementsCardBodyOn then
    totalBackingHeight = totalBackingHeight + requirementsCardHeight_Body
    if not self._cantBuySpecialCase then
      totalBackingHeight = totalBackingHeight + requirementsCardHeight_Footer
    end
  end
  local animRate = 0
  local baseUnitSize = 0.033333335
  local targetTimelinePos = totalBackingHeight * baseUnitSize
  UI.Anim(self.children.goRecipeHeader, consts.AS_Forward, "", animRate, targetTimelinePos)
end
function CardManager:UpdateRequirementsBoxPosition(cardHeight)
  local vCurrentPos = UI.GetGOLocalPosition(self.children.goRequirementsBoxGroup.goRequirementsBox)
  local vNewPos = engine.Vector.New(vCurrentPos.x, -cardHeight, vCurrentPos.z)
  UI.SetGOLocalPosition(self.children.goRequirementsBoxGroup.goRequirementsBox, vNewPos)
  UI.SetGOLocalPosition(self.children.goBlur, vNewPos)
end
function CardManager:ResetRecipeResources()
  for inputIndex = 1, resourceConsts.RECIPE_MAX_INPUTS do
    local thInputTable = self.textHandles.thRequirementsBoxGroup.thInputs[inputIndex]
    UI.SetText(thInputTable.thRecipeResource, "")
    UI.SetText(thInputTable.thRecipeResource_Icon, "")
    UI.SetText(thInputTable.thRecipeResource_Amount, "")
    local goInputTable = self.children.goRequirementsBoxGroup.goInputs[inputIndex]
    local animRate = 0
    local animStartTime = 0
    UI.Anim(goInputTable.goResourceProgressBarChild, consts.AS_Forward, "", animRate, animStartTime)
    goInputTable.goResourceProgressBarChild:Hide()
  end
end
function CardManager:UpdateRecipeInput(recipeInputIndex, recipeItem, isSellRecipe, isArtifactRecipe, primaryRecipeItem, requiresPickupsMaxedOut)
  if 4 < recipeInputIndex then
    return
  end
  local thInputTable = self.textHandles.thRequirementsBoxGroup.thInputs[recipeInputIndex]
  local requiredAmount = recipeUtil.GetRecipeItemAmount(recipeItem)
  local resourceName = recipeUtil.GetRecipeItemName(recipeItem)
  local resourceDisplayName = resourceUtil.GetDisplayName(resourceName)
  local useMacroIcon = resourceName == "Hacksilver" or resourceName == "EconomyXP"
  local resourceIcon = useMacroIcon == true and "[" .. resourceName .. "]" or iconConsts[resourceName]
  local isPickup = resourceUtil.HasFlag(resourceName, resourceConsts.RESOURCE_FLAG_PICKUP)
  local currResourceAmount = resourceUtil.GetAmount(resourceName)
  if requiresPickupsMaxedOut and isPickup then
    if pickupUtil.GetProfileStage(resourceName) ~= pickupUtil.GetMaxStage(resourceName) then
      currResourceAmount = 0
    elseif characterUtil.ItemIsEquipped(resourceName) then
      currResourceAmount = 0
      UI.SetText(self.textHandles.thRequirementsBoxGroup.thCraftText, util.GetLAMSMsg(lamsConsts.CantPurchase_UnequipResources))
    end
  end
  local currResourceProgressPercentage = currResourceAmount / requiredAmount
  local hasEnoughResource = requiredAmount <= currResourceAmount
  local resourceDisplayStyle = hasEnoughResource and "Color_Green" or "Color_Red"
  local resourceAmountText = ""
  if isPickup then
    resourceIcon = iconConsts.RecipeInputPickup
  end
  if isSellRecipe then
    if isArtifactRecipe and primaryRecipeItem ~= nil then
      local sellResourceName = recipeUtil.GetRecipeItemName(primaryRecipeItem)
      local sellResourceAmount = resourceUtil.GetAmount(sellResourceName)
      requiredAmount = requiredAmount * sellResourceAmount
    end
    resourceAmountText = util.StyleText(tostring(requiredAmount), "Color_White")
  else
    resourceAmountText = util.StyleText(tostring(currResourceAmount), resourceDisplayStyle) .. util.StyleText(tostring(" / " .. requiredAmount), "Color_White")
  end
  if resourceIcon == nil then
    resourceIcon = ""
  end
  UI.SetText(thInputTable.thRecipeResource, resourceDisplayName)
  UI.SetText(thInputTable.thRecipeResource_Icon, resourceIcon)
  UI.SetText(thInputTable.thRecipeResource_Amount, resourceAmountText)
  local goInputTable = self.children.goRequirementsBoxGroup.goInputs[recipeInputIndex]
  local animRate = 0
  local animStartTime = currResourceProgressPercentage
  UI.Anim(goInputTable.goResourceProgressBarChild, consts.AS_Forward, "", animRate, animStartTime)
end
function CardManager:UpdateAllRecipeInputs(recipeListItem, isSellRecipe)
  local recipeName = recipeUtil.RecipeListItem_GetRecipeName(recipeListItem)
  local itemsToShow = isSellRecipe and recipeUtil.GetOutputRecipeItems(recipeName) or recipeUtil.RecipeListItem_GetInputRecipeItems(recipeListItem)
  local isArtifactRecipe = recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_ARTIFACT)
  local requiresPickupsMaxedOut = recipeUtil.HasFlag(recipeName, "NGPRecipePickupMaxHack")
  local recipeInputIndex = 1
  for _, item in ipairs(itemsToShow) do
    local itemType = recipeUtil.GetRecipeItemType(item)
    local itemIsRecipe = itemType == "Recipe"
    if not itemIsRecipe and item.Consume then
      local itemName = recipeUtil.GetRecipeItemName(item)
      local isQuestItem = resourceUtil.HasFlag(itemName, resourceConsts.RESOURCE_FLAG_QUEST_ITEM)
      local isBowUpgradeItem = resourceUtil.HasFlag(itemName, resourceConsts.RESOURCE_FLAG_UPGRADE) and resourceUtil.HasFlag(itemName, resourceConsts.RESOURCE_FLAG_SON)
      local isNGPUpgradeItem = resourceUtil.HasFlag(itemName, resourceConsts.RESOURCE_FLAG_UPGRADE) and resourceUtil.HasFlag(itemName, "NGP") and not resourceUtil.HasFlag(itemName, resourceConsts.RESOURCE_FLAG_PICKUP)
      local isDummyResource = isArtifactRecipe and isQuestItem or isBowUpgradeItem or isNGPUpgradeItem
      if itemName == "ResurrectionStoneASold" or itemName == "ResurrectionStoneBSold" or itemName == "ResurrectionStoneCSold" then
        isDummyResource = true
      end
      if not isDummyResource then
        self:UpdateRecipeInput(recipeInputIndex, item, isSellRecipe, isArtifactRecipe, recipeUtil.RecipeListItem_GetPrimaryItem(recipeListItem), requiresPickupsMaxedOut)
        recipeInputIndex = recipeInputIndex + 1
      end
    end
  end
end
function CardManager:UpdateRequirementsBoxBacking(canRecipeBeMade)
  local useDefault = canRecipeBeMade or self._cantBuySpecialCase
  local backingColor = useDefault and colors.CRAFTINGSTAVE_DEFAULT or colors.CRAFTINGSTAVE_NOTENOUGH
  local lineColors = useDefault and colors.CRAFTINGSTAVE_LINES_DEFAULT or colors.CRAFTINGSTAVE_LINES_NOTENOUGH
  local imageColor = useDefault and skillTreeConsts.SkillInfoCardLockedColors.Purchased.Image or skillTreeConsts.SkillInfoCardLockedColors.Locked.Image
  util.SetGameObjectColor(self.children.goRequirementsBoxGroup.goRequirementsGroup, backingColor, "statCard_Backing2", "Layer0", "cst_EmissiveTint")
  util.SetGameObjectColor(self.children.goRequirementsBoxGroup.goRequirementsGroup, imageColor, "backingDesign_1", "LayerX", "cst_EmissiveTint")
  util.SetGameObjectColor(self.children.goRequirementsBoxGroup.goRequirementsGroup, lineColors, "mapMenu_Border", "LayerX", "cst_EmissiveTint")
  util.SetGameObjectColor(self.children.goRequirementsBoxGroup.goRequirementsGroup, lineColors, "mapMenu_Border_Animated", "LayerX", "cst_EmissiveTint")
  util.SetGameObjectColor(self.children.goRequirementsBoxGroup.goRequirementsFooter, backingColor, "statCard_Backing2", "Layer0", "cst_EmissiveTint")
  util.SetGameObjectColor(self.children.goRequirementsBoxGroup.goRequirementsFooter, imageColor, "backingDesign_1", "LayerX", "cst_EmissiveTint")
  util.SetGameObjectColor(self.children.goRequirementsBoxGroup.goRequirementsFooter, lineColors, "mapMenu_Border", "LayerX", "cst_EmissiveTint")
  if canRecipeBeMade then
    self.children.goRequirementsBoxGroup.goRequirementsUnavailableBacking:Hide()
  else
    self.children.goRequirementsBoxGroup.goRequirementsUnavailableBacking:Show()
  end
end
function CardManager:UpdateRecipeResources(recipeListItem, canRecipeBeMade)
  self._cantBuySpecialCase = false
  if recipeListItem ~= nil then
    local recipeName = recipeUtil.RecipeListItem_GetRecipeName(recipeListItem)
    local primaryRecipeItem = recipeUtil.RecipeListItem_GetPrimaryItem(recipeListItem)
    local isBuyRecipe = recipeUtil.RecipeIsForBuy(recipeName)
    local isSellRecipe = recipeUtil.RecipeIsForSell(recipeName)
    local isUpgradeRecipe = recipeUtil.IsReinforcementRecipe(recipeName)
    local hideRequirementsGroup = false
    local recipeHeaderText = ""
    local requirementsHeaderText = ""
    if isSellRecipe then
      recipeHeaderText = util.GetLAMSMsg(lamsConsts.Sell)
      requirementsHeaderText = util.GetLAMSMsg(lamsConsts.ResourcesReceived)
      if not canRecipeBeMade and (recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_ARTIFACT) or recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_RESOURCE)) then
        hideRequirementsGroup = true
        requirementsHeaderText = util.GetLAMSMsg(lamsConsts.Sold)
      end
    elseif isBuyRecipe then
      recipeHeaderText = util.GetLAMSMsg(lamsConsts.Buy)
      requirementsHeaderText = util.GetLAMSMsg(lamsConsts.ResourcesRequired)
      if not canRecipeBeMade then
        local resourceName = recipeUtil.GetRecipeItemName(primaryRecipeItem)
        local isResourceRecipe = resourceUtil.HasFlag(resourceName, resourceConsts.RESOURCE_FLAG_RESOURCE) and not recipeUtil.IsReinforcementRecipe(recipeName)
        local isRNG = resourceUtil.HasFlag(resourceName, resourceConsts.RESOURCE_FLAG_GENERATE_RUNE) or resourceUtil.HasFlag(resourceName, resourceConsts.RESOURCE_FLAG_ROLL_CONDITION)
        local isInfiniteRNG = isRNG and resourceUtil.GetMax(resourceName) >= resourceConsts.INT_MAX
        if resourceUtil.IsValidResourceName(resourceName) and resourceUtil.GetAmount(resourceName) > 0 and not isResourceRecipe and not isInfiniteRNG then
          hideRequirementsGroup = true
          requirementsHeaderText = util.GetLAMSMsg(lamsConsts.Purchased)
        end
      end
    else
      recipeHeaderText = util.GetLAMSMsg(lamsConsts.Recipe)
      requirementsHeaderText = util.GetLAMSMsg(lamsConsts.ResourcesRequired)
      if not canRecipeBeMade then
        if isUpgradeRecipe then
          local pickupName = recipeUtil.RecipeListItem_GetReinforcementPickupName(recipeListItem)
          local currStage = pickupUtil.GetProfileStage(pickupName)
          local maxStage = pickupUtil.GetMaxStage(pickupName)
          if currStage == maxStage then
            hideRequirementsGroup = true
            requirementsHeaderText = util.GetLAMSMsg(lamsConsts.AtMaxUpgrade)
          end
        elseif recipeUtil.RecipeListItem_AtLimit(recipeListItem) then
          hideRequirementsGroup = true
          requirementsHeaderText = util.GetLAMSMsg(lamsConsts.Crafted)
        end
      end
    end
    if hideRequirementsGroup then
      self._requirementsCardBodyOn = false
      self.children.goRequirementsBoxGroup.goRequirementsGroup:Hide()
    else
      self._requirementsCardBodyOn = true
      self.children.goRequirementsBoxGroup.goRequirementsGroup:Show()
      if not canRecipeBeMade then
        local thInputTable = self.textHandles.thRequirementsBoxGroup.thInputs[1]
        if isBuyRecipe then
          if recipeUtil.IsRuneCreatorRecipe(recipeName) then
            local hasEnoughMemory = runeUtil.HasMemorySpaceForRune()
            if not hasEnoughMemory then
              requirementsHeaderText = util.GetLAMSMsg(lamsConsts.TooManyRunesHeader)
              UI.SetText(thInputTable.thRecipeResource, util.GetLAMSMsg(lamsConsts.TooManyRunes))
              self._cantBuySpecialCase = true
            end
          elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_RESURRECTION_STONE) then
            local hasResStoneFlagResource = 0 < resourceUtil.GetAmount("ResurrectionStoneFlag")
            if not hasResStoneFlagResource then
              requirementsHeaderText = util.GetLAMSMsg(lamsConsts.DoNotHaveResurrectionStoneHeader)
              UI.SetText(thInputTable.thRecipeResource, util.GetLAMSMsg(lamsConsts.DoNotHaveResurrectionStone))
              self._cantBuySpecialCase = true
            end
          end
        elseif isSellRecipe then
          if recipeUtil.RecipeIsForSellRune(recipeName) then
            local runeInfo = primaryRecipeItem
            if runeInfo == nil then
              requirementsHeaderText = util.GetLAMSMsg(lamsConsts.Sold)
              UI.SetText(thInputTable.thRecipeResource, util.GetLAMSMsg(lamsConsts.SoldBody))
              self._cantBuySpecialCase = true
            end
          elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_RESURRECTION_STONE) then
            local hasResStoneFlagResource = 0 < resourceUtil.GetAmount("ResurrectionStoneFlag")
            if hasResStoneFlagResource then
              requirementsHeaderText = util.GetLAMSMsg(lamsConsts.Sold)
              UI.SetText(thInputTable.thRecipeResource, util.GetLAMSMsg(lamsConsts.SoldBackResurrectionStone))
              self._cantBuySpecialCase = true
            end
          else
            local resourceName = recipeUtil.GetRecipeItemName(primaryRecipeItem)
            if resourceUtil.IsValidResourceName(resourceName) and resourceUtil.GetAmount(resourceName) < 1 then
              requirementsHeaderText = util.GetLAMSMsg(lamsConsts.Sold)
              UI.SetText(thInputTable.thRecipeResource, util.GetLAMSMsg(lamsConsts.SoldBody))
              self._cantBuySpecialCase = true
            end
          end
        end
      end
      if self._cantBuySpecialCase then
        self.children.goRequirementsBoxGroup.goRequirementsFooter:Hide()
      else
        self:UpdateAllRecipeInputs(recipeListItem, isSellRecipe)
      end
    end
    UI.SetText(self.textHandles.thRecipeHeader, recipeHeaderText)
    UI.SetText(self.textHandles.thRequirementsBoxGroup.thRequirementsHeader, requirementsHeaderText)
    self:UpdateRequirementsBoxBacking(canRecipeBeMade)
  end
end
function CardManager:GetSoundNameID(subStateIndex, recipeName)
  local id
  if subStateIndex ~= nil then
    id = subStateIndex
    if recipeUtil.IsValidRecipeName(recipeName) then
      if subStateIndex == "Craft" then
        if recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_WEAPON_COMPONENT) then
          id = id .. "_Axe"
        elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_WEAPON_COMPONENT_BLADES) then
          id = id .. "_Blades"
        else
          id = id .. "_Armor"
        end
      elseif subStateIndex == "Upgrade" then
        if recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_AXE) or recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_WEAPON_COMPONENT) then
          id = id .. "_Axe"
        elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_BLADES) or recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_WEAPON_COMPONENT_BLADES) then
          id = id .. "_Blades"
        elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_QUIVER) then
          id = id .. "_Quiver"
        elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_SON_BOW) then
          id = id .. "_Bow"
        elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_ARMOR_TRINKET) then
          id = id .. "_Talisman"
        else
          id = id .. "_Armor"
        end
      elseif subStateIndex == "Buy" then
        if recipeUtil.RecipeIsForRunicAttack(recipeName) then
          id = id .. "_Runic_Attacks"
        elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_RESURRECTION_STONE) then
          id = id .. "_Resurrection_Stone"
        elseif recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_RUNE) or recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_GENERATE_RUNE) or recipeUtil.HasFlag(recipeName, resourceConsts.RESOURCE_FLAG_ROLL_CONDITION) then
          id = id .. "_Enchantment"
        else
          id = id .. "_Resource"
        end
      elseif subStateIndex == "Sell" then
        id = id .. "_Generic"
      end
    end
  end
  return id
end
function CardManager:UpdateHoldFill(recipeListItem, canRecipeBeMade, subStateIndex)
  local recipeName = recipeUtil.RecipeListItem_GetRecipeName(recipeListItem)
  self.holdFill:Reset()
  if subStateIndex ~= nil then
    local soundPrefix = "SND_UX_HUD_Vendor_"
    local holdSound = soundPrefix .. self:GetSoundNameID(subStateIndex, nil) .. "_Hold"
    local stopSound = "SND_UX_Vendor_Upgrade_Hold_Reset_LP"
    local successSound = soundPrefix .. self:GetSoundNameID(subStateIndex, recipeName) .. "_Success"
    self.holdFill:SetSounds(holdSound, stopSound, successSound)
  end
  local actionText = ""
  if subStateIndex ~= nil and self._isVendor == true then
    self.children.goRequirementsBoxGroup.goCraftTextPrompt:Show()
    if canRecipeBeMade then
      local isArtifactRecipe = recipeUtil.RecipeIsForSellArtifact(recipeName)
      local subStateDisplayName = isArtifactRecipe and util.GetLAMSMsg(lamsConsts.SellAll) or recipeUtil.SubmenuList_GetDisplayName(subStateIndex, self._isVendor)
      actionText = "[SquareButton] " .. util.StyleText(subStateDisplayName, "Color_Interact")
    else
      actionText = util.GetLAMSMsg(lamsConsts.CantPurchase_NotEnoughResources)
    end
  end
  UI.SetText(self.textHandles.thRequirementsBoxGroup.thCraftText, actionText)
  if canRecipeBeMade == true and self._isVendor == true then
    local show = true
    self.holdFill:Activate(show)
  else
    local show = false
    self.holdFill:Deactivate(show)
  end
end
return {CardManager = CardManager}
