local tablex = require("core.tablex")
local picklelib = require("core.pickle")
local components = require("design.components")
local DL = require("design.DesignerLibrary")
local timer = require("creature.timer")
local globalLuaHooks = require("design.GlobalLuaHooks")
globalLuaHooks.InstallHooks()
local traverselink = require("creature.traverselink")
traverselink.InstallHooks()
constants = {}
global = {}
Brain_Core = require("behavior.corebrain")
attachments = {}
local powerLevel = "1"
local pLevelInt = 0
function OnAIPostSpawn(ai)
  setupCharacter(ai)
end
function Brain_Core:OnSetPowerlevelOverrideCustom(ai, global, constants, level, isElite, forced)
  powerLevel = level
  ToggleCharacterConfig(ai, forced)
end
local axeThrowParryCooldown = 0
function OnWeaponApproaching(gameObject, attacker, weapon, side)
  if side == "front" and axeThrowParryCooldown < game.GetGameTime() then
    local ai = gameObject:GetCreature():GetAI()
    if (ai:HasMarker("AI_Attack") == false or ai:HasMarker("AI_CanBlock") == true) and ai:HasMarker("React_Flip") == false and ai:HasMarker("React_Bounce") == false and ai:HasMarker("React_Flyback") == false and ai:HasMarker("React_Spin") == false and ai:HasMarker("React_Lie_Stomach") == false and ai:HasMarker("React_SuperFlyback") == false and ai:HasMarker("React_Groundslide") == false and ai:HasMarker("AI_DoNotBlock") == false and ai:HasMarker("SonGrab") == false and ai:PickupIsAcquired("SonRune") == false and DL.GetDistanceBetweenTwoObjects(attacker, ai) > 3 then
      ai:TriggerMoveEvent("LE_Block")
      if ai:PickupIsAcquired("Brawler00_PowerLevel_Seidr") then
        axeThrowParryCooldown = game.GetGameTime() + 10
      else
        axeThrowParryCooldown = game.GetGameTime() + 6
      end
    end
  end
end
function setupCharacter(ai)
  local moveName = ""
  local aggroState = ""
  local spawnContext = ai:GetContext()
  if not ai:PickupIsAcquired("GruntMace") then
    ai:PickupAcquire("GruntMace")
  end
  if StartConfig ~= nil then
    if StartConfig.Variant ~= nil then
      global.variant = StartConfig.Variant
    end
    if StartConfig.EliteDifficulty ~= nil and StartConfig.EliteDifficulty and not ai:PickupIsAcquired("Brawler00_Elite") then
      ai:PickupAcquire("Brawler00_Elite")
    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
  ToggleCharacterConfig(ai, not game.CHECK_FEATURE("PREEMPT_SPAWN_CONFIG"))
  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
  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
  if ai:AttributeGetValue("Difficulty") == 4 then
    local cineVar = game.Level.GetVariable("CompletedCineNumber")
    if ai:PickupIsAcquired("Brawler00_PowerLevel") then
      if (180 <= cineVar and 1 >= ai:PickupGetStage("Brawler00_PowerLevel") or 250 <= cineVar and 2 >= ai:PickupGetStage("Brawler00_PowerLevel") or 380 <= cineVar and 3 >= ai:PickupGetStage("Brawler00_PowerLevel") or 490 <= cineVar and 4 >= ai:PickupGetStage("Brawler00_PowerLevel")) and (ai.GroundLevel == nil or ai.GroundLevel ~= nil and string.find(ai.GroundLevel.Name, "Msp") == nil) then
        ai:PickupAcquire("PowerLevelBoost")
      end
    elseif ai:PickupIsAcquired("Brawler00_PowerLevel_Seidr") and (180 <= cineVar and 1 >= ai:PickupGetStage("Brawler00_PowerLevel_Seidr") or 250 <= cineVar and 2 >= ai:PickupGetStage("Brawler00_PowerLevel_Seidr") or 380 <= cineVar and 3 >= ai:PickupGetStage("Brawler00_PowerLevel_Seidr") or 490 <= cineVar and 4 >= ai:PickupGetStage("Brawler00_PowerLevel_Seidr")) and (ai.GroundLevel == nil or ai.GroundLevel ~= nil and string.find(ai.GroundLevel.Name, "Msp") == nil) then
      ai:PickupAcquire("PowerLevelBoost")
    end
  end
  DL.NewGamePlusLevelBoost(ai, "Brawler00_PowerLevel")
  DL.NewGamePlusLevelBoost(ai, "Brawler00_PowerLevel_Seidr")
end
function ToggleCharacterConfig(ai, override)
  if powerLevel == "1" then
    pLevelInt = 1
  elseif powerLevel == "2" then
    pLevelInt = 2
  elseif powerLevel == "3" then
    pLevelInt = 3
  elseif powerLevel == "4" then
    pLevelInt = 4
  elseif powerLevel == "5" then
    pLevelInt = 5
  elseif powerLevel == "6" then
    pLevelInt = 6
  elseif powerLevel == "7" then
    pLevelInt = 7
  elseif powerLevel == "8" then
    pLevelInt = 8
  else
    pLevelInt = powerLevel
  end
  local rand = 0
  if global.variant == "Helwalker" then
    if not ai:PickupIsAcquired("Variant_Helwalker_MFX_Pickup") then
      ai:PickupAcquire("Variant_Helwalker_MFX_Pickup")
    end
    if override ~= nil and override == true then
      if 5 <= pLevelInt then
        rand = math.random(1, #constants.spawnConfigsHelVeryHard)
        ai:SetCharacterConfig(constants.spawnConfigsHelVeryHard[rand])
      else
        rand = math.random(1, #constants.spawnConfigsHelModerate)
        ai:SetCharacterConfig(constants.spawnConfigsHelModerate[rand])
      end
    end
    game.Audio.SetWwiseSwitch(ai, "CHR_Type", "Helwalker")
  elseif global.variant == "Default" then
    if not ai:PickupIsAcquired("Variant_Seidr_MFX_Pickup") then
      ai:PickupAcquire("Variant_Seidr_MFX_Pickup")
    end
    if ai:PickupIsAcquired("Brawler00_PowerLevel") then
      ai:PickupRelinquish("Brawler00_PowerLevel")
      ai:PickupAcquire("Brawler00_PowerLevel_Seidr")
    end
    if ai:PickupIsAcquired("Brawler00_PowerLevel_Seidr") then
      if override ~= nil and override == true then
        if 5 <= pLevelInt then
          rand = math.random(1, #constants.spawnConfigsSeidrVeryHard)
          ai:SetCharacterConfig(constants.spawnConfigsSeidrVeryHard[rand])
        else
          rand = math.random(1, #constants.spawnConfigsSeidrModerate)
          ai:SetCharacterConfig(constants.spawnConfigsSeidrModerate[rand])
        end
      end
      ai:PickupSetStage("Brawler00_PowerLevel_Seidr", pLevelInt - 1)
    else
      print("!!!!!!!! SEIDR BRAWLER00 - does not have a valid power-level pickup, so config and pickup stage are not set !!!!!!!!")
    end
    game.Audio.SetWwiseSwitch(ai, "CHR_Type", "Seidr")
  end
  timer.StartCreatureTimer(0.1, function()
    for activeWeapon in ai:IterateActiveWeapons() do
      local gameobj = activeWeapon.Weapon
      if gameobj:GetName() == "mace00" then
        if global.variant == "Helwalker" then
          if pLevelInt <= 4 then
            gameobj:SetCharacterConfig("helwalker_easy")
          else
            gameobj:SetCharacterConfig("helwalker_hard")
          end
        elseif global.variant == "Default" then
          gameobj:SetCharacterConfig("seidr")
        else
          gameobj:SetCharacterConfig("seidr")
        end
      end
    end
  end)
end
function OnAIUpdate(ai)
  components.UpdateComponents(ai, attachments)
  traverselink.OnUpdate(ai)
end
function _G.OnAICreateLuaState(ai)
  components.StartComponents(ai, attachments)
  _G.OnAICreateLuaState = nil
end
function LuaHook_ResetAxeThrowParryCooldown(ai, data)
  axeThrowParryCooldown = 0
end
function LuaHook_ClearArrow(ai, data)
  game.Combat.RemoveArrows(ai)
end
function LuaHook_MatAnim_SeidrHealOff(ai, data)
  ai:StartMaterialAnim("seidrHeal_materialAnim_OFF")
end
function LuaHookDecision_CanHeal(ai, data)
  local healthPerc = ai:MeterGetValue("Health") / ai:MeterGetMax("Health")
  local retVal = false
  if healthPerc <= 0.7 then
    retVal = true
  end
  return retVal
end
function LuaHook_CheckCanReact(ai)
  if ai:MeterGetValue("CD_ComboBreaker") >= 99 then
    return false
  end
  return true
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_MaceGlow(ai)
  PlayWeaponMaterial(ai, "mace00", "charge")
end
function LuaHook_AddBlood_Cleave_Impact(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLowerArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLeg, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLeg, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightBackUpperArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLeg, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLeg, 0.1)
end
function LuaHook_AddBlood_Brawler_RageEnter(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontUpperArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLowerArm, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.1)
  player:AddBlood(game.GameObject.eRegionId.kRightBackUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLowerArm, 0.4)
end
function LuaHook_AddBlood_Brawler_RageHeadButt(ai, data)
  local player = game.Player.FindPlayer()
  player:AddBlood(game.GameObject.eRegionId.kHead, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftChest, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kRightChest, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kFrontAbdomen, 0.6)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftFrontLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightFrontLowerArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBack, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightBack, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kBackAbdomen, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kLeftBackLowerArm, 0.2)
  player:AddBlood(game.GameObject.eRegionId.kRightBackUpperArm, 0.4)
  player:AddBlood(game.GameObject.eRegionId.kRightBackLowerArm, 0.2)
end
picklelib.Install()
function Pickle(GO)
  return {
    global = global
  }
end
function Unpickle(GO, t)
  global = t.global
end
