local statemachine = require("ai.statemachine")
local picklelib = require("core.pickle")
local Brain_Core = require("behavior.corenpcbrain")
local DL = require("design.DesignerLibrary")
local LD = require("design.LevelDesignLibrary")
local timer = require("creature.timer")
local locomotion = require("creature.locomotion")
local lookAtConsts = require("game.lookAtConsts")
local breathEffect
constants = {}
global = {}
global.currentPOI = {}
_G.lookAtPriorityOverrides = {}
global.aggroState = ""
global.navBank = "NB_DefaultBank"
constants.POICollisionRadius = 0.05
constants.navCurveData = {}
global.slowdownAllowed = true
global.stopMove = nil
global.nessecarySpeed = nil
global.checkForCorrectSpeedAndPhaseStops = nil
global.leadTheWayParams = {
  Speed = 3,
  LeaderDistance_Wait = 15,
  LeaderDistance_Continue = 10,
  LeaderDistance_Backtrack = 30,
  LeaderDistance_BacktrackDone = 20,
  FollowerDistance_CaughtUp = 5,
  FollowerDistance_Continue = 6,
  Waiting = false,
  Backtracking = false,
  Role = nil,
  TargetCreature = nil,
  TargetCreatureDir = "forward",
  TargetCreatureDirBufferPos = nil,
  TargetCreatureDirBufferRad = 1.5,
  EnableLeashing = true
}
global.followPlayerParams = {
  Speed = 4,
  Strafe = false,
  Facing = nil
}
function OnCreatureUpdate(crt)
  locomotion.AssignNavCurve(global, constants, crt)
end
function OnAIPostSpawn(ai)
  if breathEffect == nil then
    breathEffect = game.FX.Spawn("FX_kratos_Breath", nil, {
      Joint = "JOJaw1",
      GameObject = ai,
      DeleteWithCreature = true
    })
    breathEffect:SetAnimFloatChannelDriver(ai, "sliderfloatchannels._breathefxintensity")
  end
  ai:SetAIDeathCallback(ai, "DeathBehavior")
end
function OnAIUpdate(ai)
  CheckForStopping(ai)
end
function DeathBehavior(ai)
  if breathEffect ~= nil then
    breathEffect:Destroy()
    breathEffect = nil
  end
end
function _G.OnAICreateLuaState(ai)
  _G.global.selfAI = ai
  if ai.AddLookAtPriorityOverride then
    _G.thisLookAtEntry = game.AddGlobalLookAtTarget(ai, engine.Vector.New(0, 1, 0), lookAtConsts.TargetType.FriendlyAI)
    _G.lookAtPriorityOverrides.kid = ai:AddLookAtPriorityOverride(lookAtConsts.TargetType.Kid, lookAtConsts.Priority.Medium)
    _G.lookAtPriorityOverrides.hero = ai:AddLookAtPriorityOverride(lookAtConsts.TargetType.Hero, lookAtConsts.Priority.Ignore)
    _G.lookAtPriorityOverrides.badGuy = ai:AddLookAtPriorityOverride(lookAtConsts.TargetType.BadGuy, lookAtConsts.Priority.High)
    _G.lookAtPriorityOverrides.combatTarget = ai:AddLookAtPriorityOverride(lookAtConsts.TargetType.CombatTarget, lookAtConsts.Priority.Highest)
    _G.lookAtPriorityOverrides.InterestingObject = ai:AddLookAtPriorityOverride(lookAtConsts.TargetType.InterestingObject, lookAtConsts.Priority.Highest)
  end
  _G.OnAICreateLuaState = nil
end
function SetSonForcedPath(ai, path, speed, forcedType)
  local pathObj = ai.GroundLevel:FindSingleGameObject(path).Children
  local navPath = game.NavPath.New(pathObj)
  ai:SetForcedPath(forcedType or 0, speed or 1.25, navPath)
  global.UseForcedPath = true
end
function ClearSonForcedPath(ai)
  ai:ClearForcedPath()
  global.UseForcedPath = false
end
function CheckForStopping(ai)
  if global.checkForCorrectSpeedAndPhaseStops then
    local locomotionInfo = ai:GetLocomotionInfo()
    local rightfoot = false
    local leftfoot = false
    if locomotionInfo.RightFootPhase > 0.15 and locomotionInfo.RightFootPhase < 0.4 then
      leftfoot = true
    elseif 0.15 < locomotionInfo.LeftFootPhase and 0.4 > locomotionInfo.LeftFootPhase then
      rightfoot = true
    end
    local velocity = ai:GetVelocity()
    local speed = velocity:Length()
    local speedTolerance = global.nessecarySpeed + 0.3
    if speed <= speedTolerance then
      if global.stopMove == nil then
        if rightfoot then
          ai:ForceMove("BRA_WalkStopTurn0_RightFoot")
          ClearSlowdownToStop(ai)
        elseif leftfoot then
          ai:ForceMove("BRA_WalkStopTurn0_LeftFoot")
          ClearSlowdownToStop(ai)
        end
      elseif rightfoot then
        ai:ForceMove(global.stopMove)
        ClearSlowdownToStop(ai)
      end
    end
  end
end
function SetupSlowdownToStop(ai, stopMove, nessecarySpeed, destination)
  if not global.slowdownAllowed then
    return
  end
  ai:ClearMaxSpeedOverride()
  if nessecarySpeed < 1.75 then
    nessecarySpeed = 1.75
  end
  local slowdownPathTable = {destination}
  local navPath = game.NavPath.New(slowdownPathTable)
  ai:SetForcedPath(1, nessecarySpeed, navPath)
  global.UseForcedPath = true
  ai:SetDecelerationOverride(1.25)
  global.stopMove = stopMove
  global.nessecarySpeed = nessecarySpeed
  global.checkForCorrectSpeedAndPhaseStops = true
end
function ClearSlowdownToStop(ai)
  ai:ClearForcedPath()
  global.UseForcedPath = false
  ai:ClearDecelerationOverride()
  global.checkForCorrectSpeedAndPhaseStops = false
end
function LuaHook_InterruptAndClearSlowdown(ai)
  if global.checkForCorrectSpeedAndPhaseStops then
    ai:ForceMove("BRA_WalkStopTurn0_RightFoot")
    ClearSlowdownToStop(global.stopMove)
  end
end
function LuaHook_ToggleSlowdownStops(ai, slowdownActive)
  global.slowdownAllowed = slowdownActive
end
function LuaHook_SummonVineTrap(ai, data)
  local currentLevel = ai.Level
  local player = game.Player.FindPlayer()
  local targetPosition = player:GetWorldPosition()
  local targetForward = player:GetWorldForward()
  local targetLeft = player:GetWorldLeft()
  local navMeshPoint = game.NavMesh.ClosestPoint(targetPosition)
  local distanceFrontOfTarget = 0
  local distanceLeftOfTarget = 0
  local velocityMultiplier = 2.5
  local baldur = LD.GetSingleAIByMarker("baldur00")
  local baldurPosition = baldur:GetWorldPosition()
  local baldurForward = baldur:GetWorldForward()
  local baldurNavMeshPoint = game.NavMesh.ClosestPoint(baldurPosition)
  local distanceBetween = LD.GetXZDistanceBetweenTwoPoints(navMeshPoint, baldurNavMeshPoint)
  if player:IsInAir() == false and 3 < distanceBetween and DL.CheckCreatureContext(player:GetContext(), "FREYA_VINE_GRAB") == false then
    local kratosVine = game.AI.Spawn(currentLevel, navMeshPoint, targetForward, "CRT_FreyaVines00", "BRA_SpawnSnareVines")
    kratosVine:AddMarker("SnareKratos")
  end
  if baldur:IsInAir() == false and DL.CheckCreatureContext(baldur:GetContext(), "FREYA_VINE_GRAB") == false then
    local baldurVine = game.AI.Spawn(currentLevel, baldurNavMeshPoint, baldurForward, "CRT_FreyaVines00", "BRA_SpawnSnareVines")
    baldurVine:AddMarker("SnareBaldur")
  end
  local Stn980 = game.FindLevel("Stn980_BossShoulder")
  if Stn980 ~= nil then
    Stn980:CallScript("StartVineAttackBanterPhase0")
  end
end
function DisableLeashing()
  print("Leashing is disabled!")
  _G.global.leadTheWayParams.EnableLeashing = false
end
function EnableLeashing()
  print("Leashing is enabled!")
  _G.global.leadTheWayParams.EnableLeashing = true
end
function WaitGateEnter()
  print("Entered wait gate")
  local freyabb = LD.FindFreya():GetPrivateBlackboard()
  freyabb:Set("inWaitGate", true)
end
function WaitGateExit()
  print("Exited wait gate")
  local freyabb = LD.FindFreya():GetPrivateBlackboard()
  freyabb:Set("inWaitGate", false)
end
function ForceForwardSplineNavState()
  print("forcing forward mode for Freya's spline nav")
  _G.global.leadTheWayParams.Backtracking = false
  _G.global.leadTheWayParams.TargetCreatureDir = "forward"
end
function LuaHook_TurtleRise()
  local riv480 = game.FindLevel("Riv480_FreyaHouse")
  if riv480 ~= nil then
    riv480:CallScript("AudioOnRise")
  end
end
function LuaHook_CharFreyaVinesStart()
  local Foot500 = game.FindLevel("Foot500_Top")
  if Foot500 ~= nil then
    Foot500:CallScript("LuaHook_LVLFreyaVinesStart")
  end
end
function LuaHook_CharFreyaVinesEnd()
  local Foot500 = game.FindLevel("Foot500_Top")
  if Foot500 ~= nil then
    Foot500:CallScript("LuaHook_LVLFreyaVinesEnd")
  end
end
function LuaHook_CartButtonEnter()
  game.Audio.StartMusic("SND_MX_FOOT_gondola_return_in")
end
picklelib.Install()
function Pickle(GO)
  return {
    global = global
  }
end
function Unpickle(GO, t)
  global = t.global
end
function LuaHook_HeadTrack_SetForcedTarget_Kratos()
  _G.global.selfAI:ForceLookAtToObject(game.Player.FindPlayer())
end
function LuaHook_HeadTrack_SetForcedTarget_Son()
  _G.global.selfAI:ForceLookAtToObject(game.AI.FindSon())
end
function LuaHook_HeadTrack_ClearForcedTarget()
  _G.global.selfAI:ClearForcedLookAtToObject()
end
function LuaHook_HeadTrack_PrioritizeKratos()
  _G.lookAtPriorityOverrides.hero = _G.global.selfAI:AddLookAtPriorityOverride(lookAtConsts.TargetType.Hero, lookAtConsts.Priority.Highest)
end
function LuaHook_HeadTrack_DeprioritizeKratos()
  _G.lookAtPriorityOverrides.hero = _G.global.selfAI:AddLookAtPriorityOverride(lookAtConsts.TargetType.Hero, lookAtConsts.Priority.Ignore)
end
