local statemachine = require("ai.statemachine")
local tablex = require("core.tablex")
local picklelib = require("core.pickle")
local DL = require("design.DesignerLibrary")
local color = require("core.color")
Brain_Core = require("behavior.corebrain")
constants = {}
global = {}
player = nil
son = nil
phase = 1
snowBlindHitCount = 1
local hpStunAmountTotal = 0
local hpStunThreshold = 0
local healthPickupArray = {}
function CallScript_OnHealthSpawned(spawnerObject, spawnedObject)
  table.insert(healthPickupArray, 1, spawnedObject)
end
function CallScript_DespawnAllHealth(ai, level)
  for _, hpickup in pairs(healthPickupArray) do
    if hpickup ~= nil then
      level:CallScript("CallScript_DestroyHealth", hpickup)
    end
  end
end
function LuaHook_ShieldStrikeSnowBlind()
end
function OnAIPostSpawn(ai)
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  global.navData.navSpeedWalk = ai:LookupFloatConstant("NAV_SPEED_WALK")
  global.navData.navSpeedJog = ai:LookupFloatConstant("NAV_SPEED_JOG")
  ai:PickupAcquire("Magni_MFX_Pickup", 0)
  DL.NewGamePlusLevelBoostFlat(ai, 3)
end
function LuaHook_TargetSon()
  if global.targetParams ~= "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY" then
    global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY"
  end
end
function LuaHook_TargetKratos()
  if global.targetParams ~= "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY" then
    global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY"
  end
end
function LuaHook_TargetBro()
  if global.targetParams ~= "FIND_TARGET_PARAMETERS_COMBAT_BRO_ONLY" then
    global.targetParams = "FIND_TARGET_PARAMETERS_COMBAT_BRO_ONLY"
  end
end
function LuaHook_ForceModiBroRun(ai)
  local modi = GetModi(ai)
  modi:CallScript("LuaHook_ForceBroRun", modi)
end
function LuaHook_ForceModiTagTeam(ai)
  local modi = GetModi(ai)
  modi:CallScript("LuaHook_ForceTagTeam", modi)
end
function LuaHook_ClearArrow(ai, data)
  game.Combat.RemoveArrows(ai)
end
function LuaHookDecision_MagniRevive(ai, data)
  if ai:MeterGetValue("MamoRevive") <= 4 then
    return data:FindOutcomeBranchesEntry("True")
  end
  return data:FindOutcomeBranchesEntry("False")
end
function LuaHookDecision_IsTargetSon(ai, data)
  local currentTarget = ai:GetTargetCreature()
  if currentTarget == game.AI.FindSon() and _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_SON_ONLY" then
    return true
  end
  return false
end
function LuaHookDecision_IsTargetHero(ai, data)
  local currentTarget = ai:GetTargetCreature()
  if currentTarget == game.Player.FindPlayer() and _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY" then
    return true
  end
  return false
end
function LuaHookDecision_IsSonStunned(ai, data)
  local retVal = false
  if son:HasMarker("Stunned") == true or son:HasMarker("Son_KnockedDown") == true then
    retVal = true
  end
  return retVal
end
function LuaHookDecision_IsBehindPlayer(ai, data)
  local toTarget = (ai:GetWorldPosition() - player:GetWorldPosition()):Normalized()
  local isBehind = false
  if toTarget:Dot(player:GetWorldForward()) < 0.25 then
    isBehind = true
  end
  return isBehind
end
local breathEffect
function OnAIUpdate(ai)
  if breathEffect == nil then
    breathEffect = game.FX.Spawn("FX_kratos_Breath", nil, {
      Joint = "JOJaw1",
      GameObject = ai,
      DeleteWithCreature = true
    })
    breathEffect:SetAnimFloatChannelDriver(player, "sliderfloatchannels._breathfxintensity")
  end
  if ai:PickupIsAcquired("MagniSnowBlind") or ai:PickupIsAcquired("ModiSnowBlind") then
    LuaHook_TargetKratos()
  elseif ai:HasMarker("AI_Attack") == false and ai:IsPlayingMove("MOV_ForceNoTargetSwitch") == false then
    local distFromPlayer = DL.GetDistanceBetweenTwoObjects(player, ai)
    local distFromSon = DL.GetDistanceBetweenTwoObjects(son, ai)
  end
  if ai:IsPlayingMove("MOV_csShieldRush") or ai:IsPlayingMove("MOV_csShieldJump") or ai:IsPlayingMove("MOV_csShieldJumpL") then
    LuaHook_TargetKratos()
  end
  if ai:HasMarker("TargetBro") then
    LuaHook_TargetBro()
  end
end
function Brain_Core:OnHitReaction(event, ai, global, constants)
  local diff = ai:MeterGetValue("Health") - hpStunThreshold
  if diff < 0 then
    diff = 0
  end
  local progressToStun = diff / hpStunAmountTotal
  local stunVal = 100 - progressToStun * 100
  if 98 < stunVal then
    stunVal = 98
  end
  if stunVal > ai:MeterGetValue("MamoRevive") then
    ai:MeterSetValue("MamoRevive", stunVal)
  end
end
function _G.OnAICreateLuaState(ai)
  local positioning = Brain_Core:GetPositioning()
  positioning.AddStandardPositioningZone("Far", constants.fightPosDataFar, constants.fightKnowledgeInputs)
  positioning.AddStandardPositioningZone("SonTarget", constants.fightPosDataSonTarget, constants.fightKnowledgeInputs)
  _G.OnAICreateLuaState = nil
end
function PlayWeaponMaterial(ai, wepName, matAnimName)
  for gameObj in ai:IterateActiveWeapons() do
    if gameObj ~= nil and gameObj.Weapon ~= nil then
      local objWepName = gameObj.Weapon:GetName()
      if objWepName == wepName then
        gameObj.Weapon:StartMaterialAnim(matAnimName)
      end
    end
  end
end
function LuaHook_AxeReject(ai)
  local concussionParams = {}
  concussionParams = {
    Tweak = "CNC_AXE_REJECT",
    WorldLocation = ai:GetWorldPosition(),
    GameObject = ai,
    EnemyId = ai:GetID()
  }
  game.Combat.PlayConcussion(concussionParams)
end
function LuaHook_SwordON(ai)
end
function LuaHook_SwordOFF(ai)
end
function LuaHook_HandRightON(ai)
end
function LuaHook_HandRightOFF(ai)
end
function LuaHook_HandLeftON(ai)
end
function LuaHook_HandLeftOFF(ai)
end
function LuaHook_AwardLoot(ai)
  game.Loot.RollCondition("MAGNIMODI_BOSS_REWARD", "HERO", ai, ai:GetName())
end
function LuaHook_AwardXP(ai)
  game.Loot.RollCondition("MAGNIMODI_BOSS_XP", "HERO", ai, ai:GetName())
end
function GetModi(ai)
  local modi
  local creaturesAroundPlayer = player:FindEnemies(30)
  for _, thisCreature in ipairs(creaturesAroundPlayer) do
    if thisCreature ~= ai then
      modi = thisCreature
    end
  end
  return modi
end
function LuaHookDecision_MamoTagTeam(ai, data)
  local retVal = false
  local modi = GetModi(ai)
  if modi ~= nil and modi:HasMarker("ModiGrab") == false and modi:PickupIsAcquired("ModiWeakened") == false then
    retVal = true
  end
  return retVal
end
function LuaHookDecision_MamoPhaseTransition(ai, data)
  local retVal = false
  local modi = GetModi(ai)
  if modi ~= nil and modi:IsPlayingMove("MOV_HitModiWeakenedLoop") and ai:IsPlayingMove("MOV_HitMagniWeakenedLoop") then
    retVal = true
  end
  return retVal
end
function LuaHookDecision_Grab(ai, data)
  local retVal = true
  if player == nil then
    player = game.Player.FindPlayer()
  end
  if player:PickupIsAcquired("RageMode") and player:PickupGetStage("RageMode") == 1 then
    retVal = false
  end
  local modi = GetModi(ai)
  if modi ~= nil and modi:HasMarker("ModiGrab") ~= false then
    retVal = false
  end
  return retVal
end
function LuaHook_ReviveSelf(ai)
  ai:MeterSetValue("MamoRevive", 0)
  local difficulty = ai:AttributeGetValue("Difficulty")
  if difficulty == 1 then
    HealSelf(ai, 30)
  elseif difficulty == 2 then
    HealSelf(ai, 50)
  elseif difficulty == 3 then
    HealSelf(ai, 100)
  elseif difficulty == 4 then
    HealSelf(ai, 150)
  end
end
function HealSelf(ai, healAmount)
  hpStunAmountTotal = ai:MeterGetValue("Health") + healAmount - hpStunThreshold
  ai:MeterSetValue("Health", ai:MeterGetValue("Health") + healAmount)
end
function LuaHook_SetHpStunThreshold(ai)
  hpStunAmountTotal = ai:MeterGetValue("Health") - hpStunThreshold
end
function SetPhase(ai, phaseNum, newThreshold)
  phase = phaseNum
  hpStunThreshold = newThreshold
  LuaHook_SetHpStunThreshold(ai)
  ai:RemoveMarker("PhaseOne")
  ai:RemoveMarker("PhaseTwo")
  ai:RemoveMarker("PhaseThree")
  if phase == 1 then
    ai:AddMarker("PhaseOne")
  elseif phase == 2 then
    ai:AddMarker("PhaseTwo")
  elseif phase == 3 then
    ai:AddMarker("PhaseThree")
  end
end
function SetSnowblindMode(ai, snowblindMode)
  if snowblindMode then
    global.aggroState = "INCOMBAT"
    global.target = player
    if ai:PickupIsAcquired("MagniSnowBlind") == false then
      ai:PickupAcquire("MagniSnowBlind")
    end
  else
    global.aggroState = "INCOMBAT"
    global.target = nil
    if ai:PickupIsAcquired("MagniSnowBlind") then
      ai:PickupRelinquish("MagniSnowBlind")
    end
  end
end
function LuaHook_JasonTargetSon(ai)
  ai:CallScript("OnForceTempAggro", 6)
end
function Brain_Core:OnUpdateCombat(ai, global, constants, dTreeParams)
  if LuaHookDecision_IsSonStunned(ai, nil) then
    if ai:PickupIsAcquired("MamoNoRetarget") and ai:PickupGetStage("MamoNoRetarget") == 0 then
      ai:PickupRelinquish("MamoNoRetarget")
    end
    if ai:PickupIsAcquired("MamoNoRetarget") == false and ai:GetTargetCreature() == game.Player.FindPlayer() then
      ai:PickupAcquire("MamoNoRetarget")
      ai:PickupSetStage("MamoNoRetarget", 1)
    end
  end
  local currentTarget = ai:GetTargetCreature()
  if currentTarget == game.Player.FindPlayer() and _G.global.targetParams == "FIND_TARGET_PARAMETERS_COMBAT_KRATOS_ONLY" then
    if ai:PickupIsAcquired("MagniNavigateFar") then
      constants.fightKnowledgeInputs.CurrentZoneSet = "Far"
    else
      constants.fightKnowledgeInputs.CurrentZoneSet = "Default"
    end
  else
    constants.fightKnowledgeInputs.CurrentZoneSet = "SonTarget"
  end
end
function LuaHook_WarpClosest(ai, data)
  local currentLevel = ai.Level
  currentLevel:CallScript("WarpBossClosest", ai)
end
function LuaHook_CheckCanReact(ai)
  if ai:MeterGetValue("CD_ComboBreaker") >= 99 then
    return false
  else
    return true
  end
end
picklelib.Install()
function Pickle(GO)
  return {
    global = global
  }
end
function Unpickle(GO, t)
  global = t.global
end
