local colors = require("ui.colors")
local consts = require("ui.consts")
local pickupConsts = require("ui.pickupConsts")
local pickupUtil = require("ui.pickupUtil")
local resourceConsts = require("ui.resourceConsts")
local runeUtil = require("ui.runeUtil")
local util = require("ui.util")
local Player = game.Player
local UI = game.UI
local buttonChildrenObjectNames = {"button", "category"}
local buttonChildrenSubObjectNames = {
  button = {
    "text",
    "colorQuad",
    "quest_checkmark",
    "trackingIcon",
    "trackingFlourish",
    "newIcon",
    "equippedIcon",
    "equippedIcon2",
    "upgradeSlot1",
    "upgradeSlot2",
    "upgradeSlot3",
    "Toggle",
    "Slider",
    "Control"
  },
  category = {"text"}
}
local GetButtonChildrenObjectNames = function()
  return buttonChildrenObjectNames
end
local GetButtonChildrenSubObjectNames = function(childName)
  return buttonChildrenSubObjectNames[childName]
end
local ShowNotification = function(button, notificationType)
  local id = button:GetSortItem()
  return id ~= nil and notificationType ~= nil and UI.HasNotification(notificationType, id)
end
local AnimateHighlight = function(goHighlight, animStyle, animRate)
  assert(goHighlight ~= nil, "Game object passed into AnimateHighlight was nil.")
  if goHighlight ~= nil then
    local animStartPos = 0
    local animEndPos = 1
    if animStyle == consts.AS_Reverse then
      animStartPos = 1
      animEndPos = 0
    end
    if animRate == nil then
      UI.Anim(goHighlight, consts.AS_Forward, "", 0, animEndPos)
    else
      UI.Anim(goHighlight, animStyle, "", animRate, animStartPos, animEndPos)
    end
  end
end
local DefaultButtonHighlightOn = function(button, animateImmediately)
  local goButtonChild = button:GetInstancedChildObject()
  local startTime = 0
  local endTime = 0.5
  local animRate = consts.DEFAULT_BUTTON_ANIM_RATE
  if goButtonChild ~= nil then
    if animateImmediately == true then
      animRate = 0
      UI.Anim(goButtonChild, consts.AS_Forward, "", animRate, endTime)
    else
      UI.Anim(goButtonChild, consts.AS_Forward, "", animRate, startTime, endTime)
    end
  end
end
local DefaultButtonHighlightOff = function(button, animateImmediately)
  local goButtonChild = button:GetInstancedChildObject()
  local startTime = 0.5
  local endTime = 1
  local animRate = consts.DEFAULT_BUTTON_ANIM_RATE
  if goButtonChild ~= nil then
    if animateImmediately == true then
      animRate = 0
      UI.Anim(goButtonChild, consts.AS_Forward, "", animRate, endTime)
    else
      UI.Anim(goButtonChild, consts.AS_Reverse, "", animRate, startTime, endTime)
    end
  end
end
local UpdateColorQuad = function(button, color)
  local goColorQuad = button:GetChildSubObject("colorQuad")
  local goButtonChild = button:GetInstancedChildObject()
  if goColorQuad ~= nil then
    if color == nil then
      goColorQuad:Hide()
    else
      goColorQuad:Show()
      util.SetGameObjectColor(goColorQuad, color, "flatColorAnim", "Layer0", "cst_EmissiveTint")
    end
  end
  if goButtonChild ~= nil then
    local animRate = 0
    local endTime = 0
    if color == colors.RARITY[resourceConsts.RESOURCE_FLAG_PERFECT] then
      endTime = 1
    end
    UI.Anim(goButtonChild, consts.AS_Forward, "NGP_Pattern_ToggleOn", animRate, endTime)
  end
end
local UpdateIcon = function(button, iconGOName, determineVisibilityFunc)
  local goIcon = button:GetChildSubObject(iconGOName)
  if goIcon ~= nil then
    local shouldShow = determineVisibilityFunc ~= nil and determineVisibilityFunc(button)
    if shouldShow then
      goIcon:Show()
      UI.Anim(goIcon, consts.AS_ForwardCycle_NoReset, "", 1)
    else
      goIcon:Hide()
    end
  end
end
local UpdateCheckmark = function(button)
  local goCheckmark = button:GetChildSubObject("quest_checkmark")
  if goCheckmark ~= nil then
    if button:get_checked() then
      goCheckmark:Show()
    else
      goCheckmark:Hide()
    end
  end
end
local UpdateTrackingIcon = function(button, isMainQuest, isTracked)
  local goTrackingIcon = button:GetChildSubObject("trackingIcon")
  local goTrackingFlourish = button:GetChildSubObject("trackingFlourish")
  if goTrackingIcon ~= nil then
    if not isMainQuest and isTracked then
      goTrackingIcon:Show()
      goTrackingFlourish:Show()
      local animRate = 0
      local endTime = 0
      UI.Anim(goTrackingFlourish, consts.AS_Forward, "", animRate, endTime)
      local color = isMainQuest and colors.MAIN_QUEST or colors.SIDE_QUEST
      util.SetGameObjectColor(goTrackingIcon, color, "trackingIcon", "icon", "cst_EmissiveTint")
    else
      goTrackingIcon:Hide()
      goTrackingFlourish:Hide()
    end
  end
end
local TrackingIcon_AnimFlourish = function(button)
  local goTrackingFlourish = button:GetChildSubObject("trackingFlourish")
  if goTrackingFlourish ~= nil then
    local animRate = 1
    local startTime = 0
    local endTime = 1
    UI.Anim(goTrackingFlourish, consts.AS_Forward, "", animRate, startTime, endTime)
  end
end
local InitSlotButtons = function(objName)
  local goGroup = util.GetUiObjByName(objName)
  local buttonCount = 4
  for i = 1, buttonCount do
    local goButtonRefnode = goGroup:FindSingleGOByName("Button" .. tostring(i)).Child
    local animRate = 0.03 + 0.001 * math.random(-1, 1)
    UI.Anim(goButtonRefnode, consts.AS_ForwardCycle, "", animRate)
  end
end
local StatsMenuPickupSlot_HighlightOn = function(button, animateImmediately)
  local goParent = button:GetGameObject()
  local goHighlightAnim = goParent:FindSingleGOByName("itemHighlight")
  local startTime = 0
  local endTime = 0.5
  local animRate = consts.DEFAULT_BUTTON_ANIM_RATE
  if animateImmediately == true then
    animRate = 0
    UI.Anim(goHighlightAnim, consts.AS_Forward, "", animRate, endTime)
  else
    UI.Anim(goHighlightAnim, consts.AS_Forward, "", animRate, startTime, endTime)
  end
end
local StatsMenuPickupSlot_HighlightOff = function(button, animateImmediately)
  local goParent = button:GetGameObject()
  local goHighlightAnim = goParent:FindSingleGOByName("itemHighlight")
  local startTime = 0.5
  local endTime = 1
  local animRate = consts.DEFAULT_BUTTON_ANIM_RATE
  if animateImmediately == true then
    animRate = 0
    UI.Anim(goHighlightAnim, consts.AS_Forward, "", animRate, endTime)
  else
    UI.Anim(goHighlightAnim, consts.AS_Reverse, "", animRate, startTime, endTime)
  end
end
local UpdateSlotButtonColor = function(button, pickupName, color, isTalismanButton)
  local goButtonChild = button:GetInstancedChildObject()
  local goColor = goButtonChild:FindSingleGOByName("itemHighlight")
  if isTalismanButton then
    util.SetGameObjectColor(goColor, color, "itemCardCircle_Glow", "Layer0", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glassCircle_worldUI", "smoke", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glassCircle_worldUI", "smoke1", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glassCircle_worldUI", "layer1", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glassCircle_worldUI", "layer1", "cst_Tint")
  else
    util.SetGameObjectColor(goColor, color, "itemCardSquare_glow2", "Layer0", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glass_worldUI", "smoke", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glass_worldUI", "smoke1", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glass_worldUI", "Layer1", "cst_EmissiveTint")
    util.SetGameObjectColor(goButtonChild, color, "glass_worldUI", "Layer1", "cst_Tint")
  end
end
local UpdateUpgradeButtonColor = function(button, pickupName, color)
  local goButtonChild = button:GetInstancedChildObject()
  if pickupName == -1 then
    pickupName = nil
  end
  util.SetGameObjectColor(goButtonChild, color, "enchantmentButton_Glass", "Layer0", "cst_EmissiveTint")
  util.SetGameObjectColor(goButtonChild, color, "enchantmentButton_Glass", "Layer1", "cst_EmissiveTint")
  util.SetGameObjectColor(goButtonChild, color, "enchantmentButton_Glass", "Layer1", "cst_Tint")
end
local UpdateUpgradeSlot = function(goSlot, backgroundColor, hasPerks, icon, iconText)
  local goChild = goSlot.Child
  local goPerkIndicator = goChild:FindSingleGOByName("perkIndicator")
  goChild:Show()
  util.SetGameObjectColor(goChild, backgroundColor, "socket_Backing", "LayerX", "cst_EmissiveTint")
  goPerkIndicator:Hide()
  if iconText ~= nil then
    local thIconText = util.GetTextHandle(goChild, "icon_text")
    if thIconText ~= nil then
      UI.SetText(thIconText, iconText)
    end
  else
    local iconMaterialName = icon == nil and consts.EMPTY_MATERIAL_NAME or icon
    goChild:SetMaterialSwap(iconMaterialName)
  end
end
local UpdateWeaponUpgrade = function(button, slotGOName, slotName, creature)
  local goSlot = button:GetChildSubObject(slotGOName)
  if slotName == nil then
    goSlot:Hide()
  else
    goSlot:Show()
    local pickupInUpgradeSlot = pickupUtil.GetPickupNameInSlot(creature, slotName)
    local upgradeSlotColor = colors.BLACK
    local hasPerks = pickupUtil.HasPerks(pickupInUpgradeSlot)
    UpdateUpgradeSlot(goSlot, upgradeSlotColor, hasPerks, pickupInUpgradeSlot, nil)
  end
end
local UpdateRuneSocket = function(button, slotGOName, pickupName, socketName)
  local goSlot = button:GetChildSubObject(slotGOName)
  if socketName == nil then
    goSlot:Hide()
  else
    goSlot:Show()
    local runeInfo = runeUtil.GetRuneInfoInSocketFromPickup(pickupName, socketName)
    local runeID = runeUtil.GetRuneInfoRuneID(runeInfo)
    local runeColor = runeUtil.IsValidRuneID(runeID) and runeUtil.GetRuneColorFromID(runeID) or colors.BLACK
    local runeIcon = runeUtil.GetRuneIconFromID(runeID)
    local hasPerks = runeUtil.RuneInfo_HasPerks(runeInfo)
    UpdateUpgradeSlot(goSlot, runeColor, hasPerks, nil, runeIcon)
  end
end
local UpdateSlotButtonUpgradeSlots = function(button, pickupName, character)
  if util.IsStringNilOrEmpty(pickupName) then
    for index = 1, pickupConsts.MAX_SOCKET_COUNT do
      local slotGOName = "upgradeSlot" .. index
      local goSlot = button:GetChildSubObject(slotGOName)
      goSlot:Hide()
    end
  elseif pickupUtil.IsWeapon(pickupName) == true then
    local pickupSlot = button:get_item()
    local weaponUpgradeSlots = pickupUtil.GetWeaponUpgradeSlotNames(character, pickupSlot)
    for index = 1, pickupConsts.MAX_SOCKET_COUNT do
      local upgradeSlot = weaponUpgradeSlots[index]
      local slotGOName = "upgradeSlot" .. index
      UpdateWeaponUpgrade(button, slotGOName, upgradeSlot, Player.FindPlayer())
    end
  elseif pickupUtil.IsArmor(pickupName) == true then
    local socketNames = runeUtil.GetSocketNames(pickupName)
    for index = 1, pickupConsts.MAX_SOCKET_COUNT do
      local socketName = socketNames[index]
      local slotGOName = "upgradeSlot" .. index
      UpdateRuneSocket(button, slotGOName, pickupName, socketName)
    end
  end
end
return {
  GetButtonChildrenObjectNames = GetButtonChildrenObjectNames,
  GetButtonChildrenSubObjectNames = GetButtonChildrenSubObjectNames,
  ShowNotification = ShowNotification,
  AnimateHighlight = AnimateHighlight,
  DefaultButtonHighlightOn = DefaultButtonHighlightOn,
  DefaultButtonHighlightOff = DefaultButtonHighlightOff,
  UpdateColorQuad = UpdateColorQuad,
  UpdateIcon = UpdateIcon,
  UpdateCheckmark = UpdateCheckmark,
  UpdateTrackingIcon = UpdateTrackingIcon,
  TrackingIcon_AnimFlourish = TrackingIcon_AnimFlourish,
  UpdateSlotButtonColor = UpdateSlotButtonColor,
  UpdateUpgradeButtonColor = UpdateUpgradeButtonColor,
  UpdateUpgradeSlot = UpdateUpgradeSlot,
  UpdateSlotButtonUpgradeSlots = UpdateSlotButtonUpgradeSlots,
  InitSlotButtons = InitSlotButtons,
  StatsMenuPickupSlot_HighlightOn = StatsMenuPickupSlot_HighlightOn,
  StatsMenuPickupSlot_HighlightOff = StatsMenuPickupSlot_HighlightOff
}
