local statemachine = require("ai.statemachine")
local DL = require("design.DesignerLibrary")
local tablex = require("core.tablex")
local picklelib = require("core.pickle")
local components = require("design.components")
local timer = require("creature.timer")
local globalLuaHooks = require("design.GlobalLuaHooks")
globalLuaHooks.InstallHooks()
local traverselink = require("creature.traverselink")
traverselink.InstallHooks()
local Brain_Core = require("behavior.corebrain")
constants = {}
global = {}
attachments = {}
function LuaHook_IceArmorHit(ai, data)
end
function LuaHook_SetInCombatState()
  global.aggroState = "INCOMBAT"
end
function LuaHook_Shield_BlockEnterCheck(ai, data)
  local goPlayerCreature = game.Player.FindPlayer()
  local vecToPlayer = goPlayerCreature:GetWorldPosition() - ai:GetWorldPosition()
  local relativePosHero = DL.GetObjectARelativePositionToObjectB(goPlayerCreature, ai)
  local relativePosSelf = DL.GetObjectARelativePositionToObjectB(ai, goPlayerCreature)
  local defRadiusMin = 4
  local defRadiusMax = 5
  if relativePosSelf ~= "objFront" or relativePosHero ~= "objFront" or defRadiusMax < _G.global.distToPlayer then
    return data:FindOutcomeBranchesEntry("ExitBlock")
  else
    return data:FindOutcomeBranchesEntry("EnterBlock")
  end
end
function LuaHook_Shield_CoverFanatic(ai, data)
  if ai:PickupIsAcquired("GruntShield") then
    _G.global.shieldedCoverFanatic = true
  else
    _G.global.shieldedCoverFanatic = false
  end
end
function LuaHook_SonHoldInPlace(ai, data)
  local son = game.AI.FindSon()
  if DL.CheckCreatureContext(son:GetContext(), "HOLDINPLACE") == false then
    return data:FindOutcomeBranchesEntry("ExitHold")
  end
end
function LuaHookDecision_IsHeroSlowed(ai, data)
  local retVal = false
  if _G.global.target ~= nil then
    retVal = _G.global.target:PickupIsAcquired("Debuff_Hero_Frost")
  end
  return retVal
end
function LuaHookDecision_IsHelwalker(ai, data)
  if global.variant ~= nil then
    return global.variant == "HELWALKER"
  end
  return false
end
function LuaHook_Bandit_POI_ApplyColdToHotstone(ai, data)
  if global.currentPOI ~= nil then
    global.currentPOI:SendEvent("OnCreatureTriggeredEvent")
  end
end
function OnAIPostSpawn(ai)
  setupCharacter(ai)
  if ai:PickupIsAcquired("HealthThreshold") then
    ai:PickupRelinquish("HealthThreshold")
  end
end
function setupCharacter(ai)
  local player = game.Player.FindPlayer()
  local moveName = ""
  local aggroState = ""
  local spawnContext = ai:GetContext()
  local variant = ""
  local rand = 1
  if not ai:PickupIsAcquired("GruntSword") then
    ai:PickupAcquire("GruntSword")
  end
  timer.StartCreatureTimer(0.05, function()
    for activeWeapon in ai:IterateActiveWeapons() do
      local gameobj = activeWeapon.Weapon
      if gameobj:GetName() == "sword00" then
        gameobj:SetCharacterConfig("banditSword")
      end
    end
  end)
  if StartConfig ~= nil then
    if not game.CHECK_FEATURE("PREEMPT_SPAWN_CONFIG") then
      ai:SetCharacterConfig("Bandit0" .. math.random(0, 4))
    end
    if StartConfig.AggroState ~= nil then
      DL.switch(StartConfig.AggroState):caseof({
        Unaware = function()
          aggroState = "UNAWARE"
        end,
        Passive = function()
          aggroState = "PASSIVE"
        end,
        NonHostile = function()
          aggroState = "NONHOSTILE"
        end,
        InCombat = function()
          aggroState = "INCOMBAT"
        end
      })
    end
    if StartConfig.SpawnMove ~= nil then
      moveName = StartConfig.SpawnMove
    end
  end
  if ai:IsPlayingMove("MOV_Spawn") or moveName == "BRA_Spawn" then
    DL.DebugPrint(ai, "Playing MOV_Spawn")
    if aggroState == "INCOMBAT" then
      moveName = "BRA_SpawnReadyForCombat"
    else
      local rand = math.random(1, 3)
      DL.switch(rand):caseof({
        [1] = function()
          moveName = "BRA_SpawnUnaware"
          DL.DebugPrint(ai, "Picked BRA_SpawnUnaware")
        end,
        [2] = function()
          moveName = "BRA_SpawnCautious"
          DL.DebugPrint(ai, "Picked BRA_SpawnCautious")
        end,
        [3] = function()
          moveName = "BRA_SpawnVigilant"
          DL.DebugPrint(ai, "Picked BRA_SpawnVigilant")
        end,
        default = function()
          moveName = "BRA_SpawnUnaware"
        end,
        missing = function()
          moveName = "BRA_SpawnUnaware"
        end
      })
    end
  elseif ai:IsPlayingMove("MOV_SpawnEquipShield") then
    local rand = math.random(1, 6)
    DL.switch(rand):caseof({
      [1] = function()
        moveName = "BRA_SpawnEquipShield_A"
      end,
      [2] = function()
        moveName = "BRA_SpawnEquipShield_B"
      end,
      [3] = function()
        moveName = "BRA_SpawnEquipShield_C"
      end,
      [4] = function()
        moveName = "BRA_SpawnEquipShield_D"
      end,
      [5] = function()
        moveName = "BRA_SpawnEquipShield_E"
      end,
      [6] = function()
        moveName = "BRA_SpawnEquipShield_F"
      end,
      default = function()
        moveName = "BRA_SpawnEquipShield_A"
      end,
      missing = function()
        moveName = "BRA_SpawnEquipShield_A"
      end
    })
    aggroState = "INCOMBAT"
  end
  if aggroState == "" then
    if DL.CheckCreatureContext(spawnContext, "UNAWARE") then
      aggroState = "UNAWARE"
    elseif DL.CheckCreatureContext(spawnContext, "NONHOSTILE") then
      aggroState = "NONHOSTILE"
    else
      aggroState = "INCOMBAT"
    end
  end
  global.aggroState = aggroState
  if moveName ~= "" then
    ai:ForceMove(moveName)
  end
end
function OnAIUpdate(ai)
  if Brain_Core:GetDebugTable(ai) then
    local debugTable = {}
    table.insert(debugTable, {
      "Variant:",
      global.variant
    })
    Brain_Core:AddCustomDebugTable(debugTable)
  end
  components.UpdateComponents(ai, attachments)
  traverselink.OnUpdate(ai)
end
function _G.OnAICreateLuaState(ai)
  _G.OnAICreateLuaState = nil
end
picklelib.Install()
function Pickle(GO)
  return {
    global = global
  }
end
function Unpickle(GO, t)
  global = t.global
end
