local tablex = require("core.tablex")
local consts = require("ui.consts")
local buttonUtil = require("ui.buttonUtil")
local pickupConsts = require("ui.pickupConsts")
local util = require("ui.util")
local Audio = game.Audio
local UI = game.UI
local SetGOTransformInterpolated = UI.SetGOTransformInterpolated
local currentSubmenu
local GetCurrentSubmenu = function()
  return currentSubmenu
end
local SetCurrentSubmenu = function(submenu)
  currentSubmenu = submenu
end
local defaultCameraJoint = "Kratos_Default_CameraJoint"
local defaultCameraStateInfo = {
  [pickupConsts.TAG_PICKUP_KRATOS] = {
    AnimName = "uiPauseMenu_Idle",
    AnimTime = 1.2,
    StatCardJoint = "Kratos_Default_StatsJoint",
    CameraJoint = "Kratos_Default_CameraJoint"
  },
  [pickupConsts.TAG_PICKUP_SON] = {
    AnimName = "uiPauseMenu_Idle",
    AnimTime = 1.2,
    StatCardJoint = "Son_Default_StatsJoint",
    CameraJoint = "Son_Default_CameraJoint"
  }
}
local cameraStateInfo = {
  [pickupConsts.TAG_PICKUP_KRATOS] = {
    StatsKratos = {
      CameraJoint = "Kratos_Default_CameraJoint",
      AnimTime = 1.9
    },
    [pickupConsts.Slot_ArmorChest] = {
      AnimName = "uiPauseMenu_ShoulderIdle",
      StatCardJoint = "Kratos_Chest_StatsJoint",
      CameraJoint = "Kratos_Chest_CameraJoint",
      AnimTime = 1
    },
    [pickupConsts.Slot_ArmorWrist] = {
      AnimName = "uiPauseMenu_WristIdle",
      StatCardJoint = "Kratos_Bracer_StatsJoint",
      CameraJoint = "Kratos_Bracer_CameraJoint",
      AnimTime = 1.2
    },
    [pickupConsts.Slot_ArmorLegs] = {
      AnimName = "uiPauseMenu_WaistIdle",
      StatCardJoint = "Kratos_Leggings_StatsJoint",
      CameraJoint = "Kratos_Leggings_CameraJoint",
      AnimTime = 1
    },
    [pickupConsts.Slot_ArmorTrinket] = {
      AnimName = "uiPauseMenu_Idle",
      StatCardJoint = "Kratos_Talisman_StatsJoint",
      CameraJoint = "Kratos_Default_CameraJoint",
      AnimTime = 1
    },
    SocketArmor = {
      StatCardJoint = "Kratos_Socket_StatsJoint",
      CameraJoint = "Kratos_Default_CameraJoint",
      AnimTime = 1
    },
    [pickupConsts.Slot_PrimaryWeapon] = {
      StatCardJoint = "Kratos_Weapon_Axe_StatsJoint",
      CameraJoint = "Kratos_Default_CameraJoint",
      AnimTime = 1.9
    },
    [pickupConsts.Slot_WeaponSpecial_Light] = {
      CameraJoint = "Kratos_Weapon_Axe_Head_CameraJoint",
      AnimTime = 1.5
    },
    [pickupConsts.Slot_WeaponSpecial_Heavy] = {
      CameraJoint = "Kratos_Weapon_Axe_Head_CameraJoint",
      AnimTime = 1.5
    },
    [pickupConsts.Slot_WeaponComponent] = {
      StatCardJoint = "Kratos_Weapon_Axe_Hilt_StatsJoint",
      CameraJoint = "Kratos_Weapon_Axe_Hilt_CameraJoint",
      AnimTime = 1.5
    },
    [pickupConsts.Slot_ArmorShield] = {
      CameraJoint = "Kratos_Default_CameraJoint",
      AnimTime = 1.8
    },
    ArmorShieldFocused = {
      CameraJoint = "Kratos_Weapon_ShieldFocused",
      AnimTime = 1.8
    },
    [pickupConsts.Slot_Blades] = {
      CameraJoint = "Kratos_Default_CameraJoint",
      AnimTime = 1.8
    },
    [pickupConsts.Slot_WeaponSpecial_Blades_Light] = {
      CameraJoint = "Kratos_Weapon_Blades_Head_CameraJoint",
      AnimTime = 1.5
    },
    [pickupConsts.Slot_WeaponSpecial_Blades_Heavy] = {
      CameraJoint = "Kratos_Weapon_Blades_Head_CameraJoint",
      AnimTime = 1.5
    },
    [pickupConsts.Slot_WeaponComponent_Blades] = {
      CameraJoint = "Kratos_Weapon_Blades_Hilt_CameraJoint",
      AnimTime = 1.5
    },
    Resources = {
      StatCardJoint = "Kratos_Recipes_StatsJoint",
      CameraJoint = "Kratos_Default_CameraJoint"
    }
  },
  [pickupConsts.TAG_PICKUP_SON] = {
    StatsSon = {
      CameraJoint = "Son_Default_CameraJoint",
      AnimTime = 1.8
    },
    [pickupConsts.Slot_SonArmor] = {
      CameraJoint = "Son_Chest_CameraJoint",
      AnimTime = 1.2
    },
    [pickupConsts.Slot_PrimaryWeapon] = {
      CameraJoint = "Son_Weapon_CameraJoint",
      AnimTime = 1.8
    },
    [pickupConsts.Slot_SonSpecial] = {
      CameraJoint = "Son_Summon_CameraJoint",
      AnimTime = 1.35
    },
    SonBow_Exit = {
      AnimName = "uiPauseMenu_Idle",
      AnimTime = 1.0E-4,
      StatCardJoint = "Kratos_Default_StatsJoint",
      CameraJoint = "Kratos_Default_CameraJoint"
    }
  }
}
local SetTransform = function(goObjToMove, goObjToMoveTo, nameOfJointToMoveTo)
  assert(goObjToMove ~= nil, "No Game object to move was defined for animationUtil.SetTransformInterpolated")
  assert(goObjToMoveTo ~= nil, "No destination transform was defined for animationUtil.SetTransformInterpolated")
  UI.SetGOTransform(goObjToMove, goObjToMoveTo, nameOfJointToMoveTo)
end
local SetTransformInterpolated = function(goObjToMove, goObjToMoveTo, nameOfJointToMoveTo, animTime, useWorldSpace)
  assert(goObjToMove ~= nil, "No Game object to move was defined for animationUtil.SetTransformInterpolated")
  assert(goObjToMoveTo ~= nil, "No destination transform was defined for animationUtil.SetTransformInterpolated")
  UI.SetGOTransformInterpolated(goObjToMove, goObjToMoveTo, nameOfJointToMoveTo, animTime, useWorldSpace, consts.Interp_Smoothstep)
end
local AnimatePickupSlotPositions = function(pickupSlotsList, selectedJointName, buttonHighlightFunction)
  assert(pickupSlotsList ~= nil, "pickupSlotsList passed to animationUtil.AnimatePickupSlotPositions was nil.")
  local selectedButton = pickupSlotsList:GetSelectedButton()
  local selectedItem = selectedButton:get_item()
  local animateImmediately = true
  if buttonHighlightFunction == nil then
    buttonUtil.StatsMenuPickupSlot_HighlightOn(selectedButton, animateImmediately)
  else
    buttonHighlightFunction(selectedButton, animateImmediately)
  end
  for buttonIndex = 1, pickupSlotsList:GetButtonCount() do
    local currButton = pickupSlotsList:GetButton(buttonIndex)
    local goButton = currButton:GetGameObject()
    if goButton ~= nil then
      local currItem = currButton:get_item()
      local fadeAlpha
      local fadeTime = 0.1
      local animRate = 1
      local jointName
      local targetTimelinePos = 1
      if currItem == selectedItem then
        fadeAlpha = 1
        jointName = selectedJointName
      else
        fadeAlpha = 0
        jointName = "PickupSlot_Offscreen" .. buttonIndex
      end
      currButton:AlphaFade(fadeAlpha, fadeTime)
      local goList = util.GetUiObjByName("PickupSlotList")
      local goNewIcon = goList:FindSingleGOByName("newIcon" .. tostring(buttonIndex))
      fadeAlpha = 0
      UI.AlphaFade(goNewIcon, fadeAlpha, fadeTime)
      local goJoints = util.GetUiObjByName("PickupSlotJoints")
      local animTime = 0
      local useWorldSpace = false
      SetTransformInterpolated(goButton, goJoints, jointName, animTime, useWorldSpace)
    end
  end
end
local SetUpgradeSlotPositions = function(runeSlotsList, animTime)
  assert(runeSlotsList ~= nil, "runeSlotsList passed to animationUtil.SetUpgradeSlotPositions was nil.")
  for buttonIndex = 2, runeSlotsList:GetButtonCount() do
    local currButton = runeSlotsList:GetButton(buttonIndex)
    local goButton = currButton:GetGameObject()
    if goButton ~= nil then
      local goJoints = util.GetUiObjByName("UpgradeSlotJoints")
      local jointName = "UpgradeSlot_InCard" .. tostring(buttonIndex - 1)
      local useWorldSpace = false
      SetTransformInterpolated(goButton, goJoints, jointName, animTime, useWorldSpace)
    end
  end
end
local ResetPickupSlotPositions = function(pickupSlotsList, forUpgradeSlots)
  assert(pickupSlotsList ~= nil, "pickupSlotsList passed to animationUtil.ResetPickupSlotPositions was nil.")
  local selectedItem = pickupSlotsList:GetSelectedItem()
  local goPauseCameraParent = util.GetUiObjByName("pauseCameraParent")
  for buttonIndex = 1, pickupSlotsList:GetButtonCount() do
    local currButton = pickupSlotsList:GetButton(buttonIndex)
    local goButton = currButton:GetGameObject()
    if goButton ~= nil then
      local fadeTime = 0.5
      local fadeAlpha = 1
      local jointName = (forUpgradeSlots and "UpgradeSlot_Default" or "PickupSlot_Default") .. buttonIndex
      currButton:AlphaFade(fadeAlpha, fadeTime)
      local goList = util.GetUiObjByName(forUpgradeSlots and "UpgradeSocketList" or "PickupSlotList")
      local goNewIcon = goList:FindSingleGOByName("newIcon" .. tostring(buttonIndex))
      if goNewIcon then
        UI.AlphaFade(goNewIcon, fadeAlpha, fadeTime)
      end
      local goJoints = util.GetUiObjByName(forUpgradeSlots and "UpgradeSlotJoints" or "PickupSlotJoints")
      local animTime = 0
      local useWorldSpace = false
      SetTransformInterpolated(goButton, goJoints, jointName, animTime, useWorldSpace)
    end
  end
end
local wasSelected = false
local SetCursorSelected = function(goCursorRefnode, isSelected, forSkillTree)
  local goSelectedCursorJoints = goCursorRefnode:FindSingleGOByName("Root")
  local goCursor = goSelectedCursorJoints:FindSingleGOByName("Mesh_Selected")
  local goCursor_Inner = goSelectedCursorJoints:FindSingleGOByName("Mesh_Unselected")
  local targetJointName
  if forSkillTree then
    targetJointName = isSelected and "cursorJoint_SkillTree_Selected" or "cursorJoint_SkillTree_Unselected"
  else
    targetJointName = isSelected and "cursorJoint_Selected" or "cursorJoint_Unselected"
  end
  goCursor:Show()
  goCursor_Inner:Show()
  if isSelected and not wasSelected then
    Audio.PlaySound("SND_UX_Menu_Reticle_Hover_Over_Tick_Open")
    wasSelected = true
  elseif not isSelected and wasSelected then
    Audio.PlaySound("SND_UX_Menu_Reticle_Hover_Over_Tick_Close")
    wasSelected = false
  end
  local animTime = 0.2
  SetTransformInterpolated(goCursor, goSelectedCursorJoints, targetJointName .. tostring(1), animTime, false)
  SetTransformInterpolated(goCursor_Inner, goSelectedCursorJoints, targetJointName .. tostring(2), animTime, false)
end
local FadeIn = function(goRefnode, targetTime)
  local time = 0
  local targetAlpha = 0
  UI.AlphaFade(goRefnode, targetAlpha, time)
  time = util.GetValueWithDefault(targetTime, 1)
  targetAlpha = 1
  UI.AlphaFade(goRefnode, targetAlpha, time)
end
local FadeOut = function(goRefnode, targetTime)
  local time = 0
  local targetAlpha = 1
  UI.AlphaFade(goRefnode, targetAlpha, time)
  time = util.GetValueWithDefault(targetTime, 1)
  targetAlpha = 0
  UI.AlphaFade(goRefnode, targetAlpha, time)
end
local DoTransitionAnim = function(goRefnode, args)
  assert(goRefnode ~= nil, "No gameobject passed into animationUtil.DoTransitionAnim.")
  local fadeAlpha_Start = util.GetValueWithDefault(args.FadeAlpha_Start, 0)
  local fadeAlpha_End = util.GetValueWithDefault(args.FadeAlpha_End, 1)
  local fadeAlpha_Time = util.GetValueWithDefault(args.FadeAlpha_Time, 0.6)
  local position_Offset = util.GetValueWithDefault(args.LocalPosition_Offset, engine.Vector.New(0, -0.1, -4))
  local position_Target = util.GetValueWithDefault(args.LocalPosition_Target, engine.Vector.New(0, 0, 0))
  local translationTime = util.GetValueWithDefault(args.TranslationTime, 0.3)
  local interplationMode = util.GetValueWithDefault(args.InterpolationMode, consts.Interp_Smoothstep)
  local time = 0
  UI.AlphaFade(goRefnode, fadeAlpha_Start, time)
  UI.AlphaFade(goRefnode, fadeAlpha_End, fadeAlpha_Time)
  local vStartPos = position_Target + position_Offset
  local vTargetPos = position_Target
  local useWorldSpace = false
  UI.SetGOTransformInterpolated(goRefnode, vStartPos, 0, useWorldSpace, interplationMode)
  UI.SetGOTransformInterpolated(goRefnode, vTargetPos, translationTime, useWorldSpace, interplationMode)
  goRefnode:Show()
end
local DoDefaultTransitionAnim = function(goRefnode)
  local fadeAlpha = 0
  local time = 0
  UI.AlphaFade(goRefnode, fadeAlpha, time)
  time = 0
  fadeAlpha = 1
  UI.AlphaFade(goRefnode, fadeAlpha, time)
end
local DoDefaultTransitionOffAnim = function(goRefnode, additionalOffset)
  local fadeAlpha = 1
  local time = 0
  UI.AlphaFade(goRefnode, fadeAlpha, time)
  time = 0.5
  fadeAlpha = 0
  UI.AlphaFade(goRefnode, fadeAlpha, time)
  local positionOffset = engine.Vector.New(0, -0.25, -4)
  local positionTarget = engine.Vector.New(0, 0, 0)
  local vStartPos = positionTarget
  local vTargetPos = positionTarget + positionOffset
  if additionalOffset then
    vStartPos = vStartPos + additionalOffset
    vTargetPos = vTargetPos + additionalOffset
  end
  local useWorldSpace = false
  UI.SetGOTransformInterpolated(goRefnode, vStartPos, 0, useWorldSpace)
  UI.SetGOTransformInterpolated(goRefnode, vTargetPos, 0.3, useWorldSpace)
end
local Journal_PlayAnimation = function(goJournal, animation, start, rate)
  if goJournal ~= nil then
    rate = util.Clamp(rate, -5, 5)
    if rate ~= 0 then
      goJournal:JumpAnimationToPercent(start, {Animation = animation})
      goJournal:PlayAnimationToEnd({Animation = animation, Rate = rate})
    end
  end
end
local Journal_SinglePageFlip = function(goJournal, rate)
  local start = 0
  if rate < 0 then
    start = 1
  end
  Journal_PlayAnimation(goJournal, "pageTurn03", start, rate)
end
local Journal_MultiPageFlip = function(goJournal, rate)
  local start = 0
  if rate < 0 then
    start = 1
  end
  Journal_PlayAnimation(goJournal, "multiPageTurn03", start, rate)
end
local MoveWorldUIMainList = function(jointName)
  local goList = util.GetUiObjByName("PickupList")
  local goParent = util.GetUiObjByName("pauseCameraParent")
  local animTime = 1.0E-5
  local useWorldSpace = false
  SetTransformInterpolated(goList, goParent, jointName, animTime, useWorldSpace)
end
local GetCameraStateInfo = function(character, pickupSlotName)
  if pickupSlotName == nil then
    return defaultCameraStateInfo[character]
  else
    return cameraStateInfo[character][pickupSlotName]
  end
end
local Tutorial_DoDefaultTransitionAnim = function(goRefnode, additionalOffset)
  local positionOffset = engine.Vector.New(0, -0.1, -4)
  local positionTarget = engine.Vector.New(0, 0, 0)
  local vStartPos = positionTarget + positionOffset
  local vTargetPos = positionTarget
  if additionalOffset then
    vStartPos = vStartPos + additionalOffset
    vTargetPos = vTargetPos + additionalOffset
  end
  local useWorldSpace = false
  UI.SetGOTransformInterpolated(goRefnode, vStartPos, 0, useWorldSpace)
  UI.SetGOTransformInterpolated(goRefnode, vTargetPos, 0.3, useWorldSpace)
end
local Tutorial_SetGOTransformInterpolated = function(goRefnode, additionalOffset)
  local positionTarget = engine.Vector.New(0, 0, 0)
  local vTargetPos = positionTarget + additionalOffset
  local useWorldSpace = false
  UI.SetGOTransformInterpolated(goRefnode, vTargetPos, 0, useWorldSpace)
end
local SetVideoQuadVisibility = function(value)
  local goSkillInfoCard = util.GetUiObjByName("skillinfocard")
  local goCardComponent = goSkillInfoCard:FindSingleGOByName("cardComponent_video")
  local jidVideoPlane = goCardComponent.Child:GetJointIndex("skillVideoPlane")
  if value then
    goCardComponent.Child:ShowJoint(jidVideoPlane)
  else
    goCardComponent.Child:HideJoint(jidVideoPlane)
  end
end
local currentlyPlayingVideo
local PlayVideo = function(videoName)
  if videoName ~= currentlyPlayingVideo then
    UI.VideoUnload()
    currentlyPlayingVideo = nil
    if videoName ~= nil then
      UI.VideoPlay(videoName)
      currentlyPlayingVideo = videoName
    end
  end
end
local GetMysteryVideoName = function(pickup)
  return "HiddenArrowSkills"
end
local ClearVideo = function()
  PlayVideo(nil)
end
function ResetCamera(currentCharacter, instant)
  local goCameraParent = util.GetUiObjByName("pauseCameraParent")
  local goStatCardTransformsParent = util.GetUiObjByName("StatsMenuJoints")
  local cameraJoint = currentCharacter == pickupConsts.TAG_PICKUP_KRATOS and "Kratos_Default_CameraJoint" or "Son_Default_CameraJoint"
  local statsCardJoint = currentCharacter == pickupConsts.TAG_PICKUP_KRATOS and "Kratos_Default_StatsJoint" or "Son_Default_StatsJoint"
  local animTime = instant and 1.0E-5 or 1
  local useWorldSpace = true
  SetTransformInterpolated(goCameraParent, goStatCardTransformsParent, cameraJoint, animTime, useWorldSpace)
end
function InitCamera(stateName)
  local cameraInitJointName = defaultCameraJoint
  if stateName ~= nil then
    cameraInitJointName = cameraStateInfo[pickupConsts.TAG_PICKUP_KRATOS][stateName].CameraJoint
  end
  local useWorldSpace = false
  local goCameraParent = util.GetUiObjByName("pauseCameraParent")
  local goStatCardTransformsParent = util.GetUiObjByName("StatsMenuJoints")
  SetTransformInterpolated(goCameraParent, goStatCardTransformsParent, cameraInitJointName, 0, useWorldSpace)
  SetTransformInterpolated(goCameraParent, goStatCardTransformsParent, cameraInitJointName, 1.0E-4, useWorldSpace)
end
function UpdateCamera(state, character, currentSlotName)
  assert(character ~= nil, "Character passed itno StatsMenu::UpdateCamera was nil!")
  local defaultAnimTime = 1.8
  local defaultCameraStateInfo = GetCameraStateInfo(character, nil)
  local currentCameraStateInfo = GetCameraStateInfo(character, currentSlotName)
  if currentCameraStateInfo == nil then
    currentCameraStateInfo = defaultCameraStateInfo
  end
  local currCharAnimName = currentCameraStateInfo.AnimName
  local currCameraJoint = currentCameraStateInfo.CameraJoint
  if currCameraJoint ~= nil then
    local currCharAnimTime = currentCameraStateInfo.AnimTime ~= nil and currentCameraStateInfo.AnimTime or defaultAnimTime
    local useWorldSpace = true
    local goCameraParent = util.GetUiObjByName("pauseCameraParent")
    local goStatCardTransformsParent = util.GetUiObjByName("StatsMenuJoints")
    SetTransformInterpolated(goCameraParent, goStatCardTransformsParent, currCameraJoint, currCharAnimTime, useWorldSpace)
  end
end
function InitMenuState(state, character, currentSlotName, initCamera)
  initCamera = util.GetValueWithDefault(initCamera, false)
  local defaultAnimTime = 1.0E-5
  local defaultCameraStateInfo = GetCameraStateInfo(character, nil)
  local currentCameraStateInfo = GetCameraStateInfo(character, currentSlotName)
  local useWorldSpace = true
  if currentCameraStateInfo == nil then
    currentCameraStateInfo = defaultCameraStateInfo
  end
  local currCharAnimName = currentCameraStateInfo.AnimName
  local currCameraJoint = currentCameraStateInfo.CameraJoint
  local currStatsCardJoint = currentCameraStateInfo.StatCardJoint ~= nil and currentCameraStateInfo.StatCardJoint or defaultCameraStateInfo.StatCardJoint
  local goCardsParent = util.GetUiObjByName("InfoCards")
  local goStatCardTransformsParent = util.GetUiObjByName("StatsMenuJoints")
  if initCamera then
    InitCamera(currentSlotName)
  end
  if currentSlotName ~= nil then
    UpdateCamera(state, character, currentSlotName)
  end
end
local SpawnFX = function(particleName, gameObject, joint)
  game.FX.Spawn(particleName, nil, {
    AutoDelete = true,
    GameObject = gameObject,
    Joint = joint,
    IsUIFX = true
  })
end
return {
  GetCurrentSubmenu = GetCurrentSubmenu,
  SetCurrentSubmenu = SetCurrentSubmenu,
  SetTransform = SetTransform,
  SetTransformInterpolated = SetTransformInterpolated,
  FadeIn = FadeIn,
  FadeOut = FadeOut,
  DoTransitionAnim = DoTransitionAnim,
  DoDefaultTransitionAnim = DoDefaultTransitionAnim,
  DoDefaultTransitionOffAnim = DoDefaultTransitionOffAnim,
  MoveWorldUIMainList = MoveWorldUIMainList,
  AnimatePickupSlotPositions = AnimatePickupSlotPositions,
  ResetPickupSlotPositions = ResetPickupSlotPositions,
  SetUpgradeSlotPositions = SetUpgradeSlotPositions,
  SetCursorSelected = SetCursorSelected,
  Journal_SinglePageFlip = Journal_SinglePageFlip,
  Journal_MultiPageFlip = Journal_MultiPageFlip,
  GetCameraStateInfo = GetCameraStateInfo,
  ResetCamera = ResetCamera,
  InitCamera = InitCamera,
  UpdateCamera = UpdateCamera,
  InitMenuState = InitMenuState,
  Tutorial_DoDefaultTransitionAnim = Tutorial_DoDefaultTransitionAnim,
  Tutorial_SetGOTransformInterpolated = Tutorial_SetGOTransformInterpolated,
  PlayVideo = PlayVideo,
  ClearVideo = ClearVideo,
  GetMysteryVideoName = GetMysteryVideoName,
  SpawnFX = SpawnFX
}
