local statemachine = require("ai.statemachine")
local tablex = require("core.tablex")
local picklelib = require("core.pickle")
local DL = require("design.DesignerLibrary")
local uiCalls = require("ui.uicalls")
local navbranchlogic = require("creature.navBranchLogic_LargeNonStrafe")
local mpicon = require("ui.mpicon")
local timer = require("level.timer")
print("Golem00 main start")
Brain_Core = require("behavior.corebrain")
constants = {}
global = {}
local golemCreature, bodyType, creatureName
local uniqueGolemName = "Ancient"
local isCoreHidden = false
local bossHealthBarOn = false
local lastGrenadeArcIndex = 5
local grenadeInteract = false
local grenadeSpawnCount = 0
local grenadeHelpTextThresh = 6
local rageGrabTextShow = false
local fwdGrenadeSpawnArc1, fwdGrenadeSpawnArc2, fwdGrenadeSpawnArc3, fwdRandGrenadeSpawnArcs, randGrenadeSpawnArc1, randGrenadeSpawnArc2, randGrenadeSpawnArc3, randGrenadeSpawnArc7, randGrenadeSpawnArc8, randGrenadeSpawnArc9, randGrenadeSpawnArc0, randGrenadeSpawnArcs
function OnAIPostSpawn(ai)
  fwdGrenadeSpawnArc1 = engine.Vector.New(0, 4, -4)
  fwdGrenadeSpawnArc2 = engine.Vector.New(1.5, 4, -4.4)
  fwdGrenadeSpawnArc3 = engine.Vector.New(-1.5, 4, -4.8)
  fwdRandGrenadeSpawnArcs = {
    fwdGrenadeSpawnArc1,
    fwdGrenadeSpawnArc2,
    fwdGrenadeSpawnArc3
  }
  randGrenadeSpawnArc1 = engine.Vector.New(0, 4, -5)
  randGrenadeSpawnArc2 = engine.Vector.New(-5, 4, 0)
  randGrenadeSpawnArc3 = engine.Vector.New(5, 4, 0)
  randGrenadeSpawnArc7 = engine.Vector.New(-4, 4, -4)
  randGrenadeSpawnArc8 = engine.Vector.New(4, 4, -4)
  randGrenadeSpawnArc9 = engine.Vector.New(-3, 3, -3)
  randGrenadeSpawnArc0 = engine.Vector.New(3, 3, -3)
  randGrenadeSpawnArcs = {
    randGrenadeSpawnArc1,
    randGrenadeSpawnArc3,
    randGrenadeSpawnArc7,
    randGrenadeSpawnArc8,
    randGrenadeSpawnArc9,
    randGrenadeSpawnArc0,
    randGrenadeSpawnArc2
  }
  setupCharacter(ai)
end
function Brain_Core:OnSetPowerlevelOverrideCustom(ai, global, constants, level, isElite, forced)
  creatureName = ai:GetName()
  ToggleCharacterConfig(ai, forced)
end
function LuaHook_ShowHealth(ai)
  if not bossHealthBarOn then
    mpicon.level.Create(ai:GetGameObject(), "BOSS_HEALTH_BAR_GOLEM")
    mpicon.level.SetTextObjectText(ai, "BOSS_HEALTH_BAR_GOLEM", "bossName", uniqueGolemName)
    mpicon.level.SetTextObjectText(ai, "BOSS_HEALTH_BAR_GOLEM", "icon", "\198\163")
    bossHealthBarOn = true
    mpicon.level.PlayAnimation(ai, "BOSS_HEALTH_BAR_GOLEM", 0, "bossHealthBar_ToggleStunMeterOn")
  end
end
function LuaHook_HideHealth(ai)
  if bossHealthBarOn then
    mpicon.level.Off(ai:GetGameObject(), "BOSS_HEALTH_BAR_GOLEM")
    bossHealthBarOn = false
  end
end
function setupCharacter(ai)
  local moveName = ""
  local spawnContext = ai:GetContext()
  golemCreature = ai
  golemCreature:PickupAcquire("Golem_MFX_Pickup", 0)
  creatureName = ai:GetName()
  global.coreHits = 0
  global.coreJointIndex = ai:GetJointIndex("WeakspotCoreJoint")
  if global.coreJointIndex ~= nil then
    isCoreHidden = true
    ai:HideJoint(global.coreJointIndex)
  else
    print("******* Golem - coreJointIndex is nil, so core collision is stuck on and is available for hits")
  end
  if StartConfig ~= nil then
    if StartConfig.BodyType ~= nil then
      bodyType = StartConfig.BodyType
    end
    if bodyType ~= "SoulEater_v1" and bodyType ~= "Woodland_v1" and not ai:PickupIsAcquired("Labor_Ancients") then
      ai:PickupAcquire("Labor_Ancients")
    end
    if StartConfig.SpawnMove ~= nil then
      moveName = StartConfig.SpawnMove
    end
  end
  ToggleCharacterConfig(ai, not game.CHECK_FEATURE("PREEMPT_SPAWN_CONFIG"))
  if moveName ~= "" then
    ai:ForceMove(moveName)
  end
  ai:PickupAcquire("GolemCoreState")
  if ai:PickupIsAcquired("GolemCoreState") then
    ai:PickupSetStage("GolemCoreState", 0)
  end
  if moveName ~= "MOV_SpawnDormantIdle" and moveName ~= "BRA_SpawnDormant" and moveName ~= "MOV_SpawnDormantIdle_LuaAlertOnly" and moveName ~= "BRA_SpawnDormant_LuaAlertOnly" then
    ai:PickupAcquire("GolemCoreStateFX")
    if ai:PickupIsAcquired("GolemCoreStateFX") then
      ai:PickupSetStage("GolemCoreStateFX", 0)
    end
  end
  if ai.SetInfluenceConeAngle ~= nil then
    ai:SetInfluenceConeAngle(65)
    ai:SetInfluenceConeLength(12)
    ai:SetInfluenceConeIntensity(0.05)
    ai:SetInfluenceConeDecay(game.Creature.InfluenceConeDecay.kNoDecay)
    ai:SetInfluenceConeIsEnabled(true)
  end
  if ai.GroundLevel ~= nil and string.find(ai.GroundLevel.Name, "Msp100_") ~= nil and ai:GetWorldPosition().y < 30 then
    ai:PickupAcquire("MuspelheimPenalty")
  end
  DL.NewGamePlusLevelBoost(ai, "Golem00_PowerLevel")
  DL.NewGamePlusLevelBoost(ai, "Golem10_PowerLevel")
  DL.NewGamePlusLevelBoost(ai, "Golem20_PowerLevel")
  DL.NewGamePlusLevelBoost(ai, "Golem30_PowerLevel")
end
function ToggleCharacterConfig(ai, override)
  if bodyType ~= nil then
    if not ai:PickupIsAcquired("GolemConfigVersion") then
      ai:PickupAcquire("GolemConfigVersion")
    end
    if creatureName == "golem00" then
      ai:PickupSetStage("Golem_MFX_Pickup", 1)
      if bodyType == "SoulEater_v2" then
        uniqueGolemName = "[MSG:" .. 39422 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("souleater_veryhard")
        end
        ai:PickupSetStage("GolemConfigVersion", 1)
      else
        uniqueGolemName = "[MSG:" .. 39417 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("souleater_moderate")
        end
      end
    elseif creatureName == "golem10" then
      if bodyType == "Woodland_v2" then
        uniqueGolemName = "[MSG:" .. 39423 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("woodland_veryhard")
        end
        ai:PickupSetStage("GolemConfigVersion", 1)
      else
        uniqueGolemName = "[MSG:" .. 39416 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("woodland_moderate")
        end
      end
    elseif creatureName == "golem20" then
      if bodyType == "Onyx_v2" then
        uniqueGolemName = "[MSG:" .. 39419 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("onyx_veryhard")
        end
        ai:PickupSetStage("GolemConfigVersion", 1)
      else
        uniqueGolemName = "[MSG:" .. 39418 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("onyx_moderate")
        end
      end
    elseif creatureName == "golem30" then
      if bodyType == "Frost_v2" then
        uniqueGolemName = "[MSG:" .. 39421 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("frost_veryhard1")
        end
        ai:PickupSetStage("GolemConfigVersion", 1)
      else
        uniqueGolemName = "[MSG:" .. 39420 .. "]"
        if override ~= nil and override == true then
          ai:SetCharacterConfig("frost_moderate")
        end
      end
    else
      if override ~= nil and override == true then
        ai:SetCharacterConfig("souleater_moderate")
      end
      print("!!!! Golem has no NAME, so setting a default config.  THIS IS BAD!")
    end
  end
end
function LuaHook_SetParamsFromGrenade(ai)
  grenadeInteract = true
end
function ShowGrenadeHelpText()
  uiCalls.SendSidebarDesignerMessage({
    Text = 40935,
    MessageVariant = uiCalls.msgParam.SIDEBAR_MEDIUM,
    DisplayTime = 12
  })
end
function OnAIUpdate(ai)
  if ai:PickupIsSlotUsed("Frost") then
    ai:PickupRelinquish("Debuff_Slow")
  end
  if ai:HasMarker("GolemStunned") then
    global.DTree = "DTR_GOLEM_STUNNED"
  elseif not ai:HasMarker("GolemStunned") then
    global.DTree = "DTR_GOLEM_OFFENSIVE"
  end
end
function _G.OnAICreateLuaState(ai)
  _G.OnAICreateLuaState = nil
end
function Brain_Core:OnUpdateMotion(ai, global, constants, actuatorData, avoidanceArgs)
  if (global.target:GetWorldPosition() - ai:GetWorldPosition()):Length() > 16 then
    actuatorData.Strafe = false
  else
    actuatorData.Strafe = global.navData.isStrafing
  end
end
function Brain_Core:OnEnterCombat(ai, global, constants)
  LuaHook_ShowHealth(ai, nil)
  _G.global.navBank = constants.CombatNavBank
  ai:SetNavBank(constants.CombatNavBank)
  if not ai:PickupIsAcquired("GolemCoreStateFX") then
    ai:PickupAcquire("GolemCoreStateFX")
  end
  if not ai:PickupIsAcquired("GolemCoreState") then
    ai:PickupAcquire("GolemCoreState")
  end
  if ai:PickupIsAcquired("GolemCoreStateFX") then
    ai:PickupSetStage("GolemCoreStateFX", 1)
  end
  if ai:PickupIsAcquired("GolemCoreState") then
    ai:PickupSetStage("GolemCoreState", 1)
  end
  GolemHelpTextLevelCall(ai, "LuaHook_StartGolemHelpTimer")
end
function Brain_Core:OnExitCombat(ai, global, constants)
  LuaHook_HideHealth(ai, nil)
  _G.global.navBank = constants.DefaultNavBank
  ai:SetNavBank(constants.DefaultNavBank)
  if ai:PickupIsAcquired("GolemCoreStateFX") then
    ai:PickupSetStage("GolemCoreStateFX", 0)
  end
  if ai:PickupIsAcquired("GolemCoreState") then
    ai:PickupSetStage("GolemCoreState", 0)
  end
  GolemHelpTextLevelCall(ai, "LuaHook_StopGolemHelpTimer")
end
function GolemHelpTextLevelCall(ai, luaHook)
  if ai ~= nil and ai.HitPoints > 0 then
    local level = game.FindLevel("TB_Golem")
    if level == nil then
      level = game.FindLevel("Alf370_MoatScripting")
    end
    if level == nil then
      level = game.FindLevel("Xpl400_HuldraMines")
      if level ~= nil then
        grenadeHelpTextThresh = 3
      end
    end
    if level ~= nil then
      level:CallScript(luaHook, golemCreature)
    end
  end
end
picklelib.Install()
function Pickle(GO)
  print("global.target = ", global.target)
  return {
    global = global
  }
end
function Unpickle(GO, t)
  print("unpickled global.target = ", t.global.target)
  global = t.global
end
function LuaHook_SpawnGrenade(C, data)
  print("lua hook - spawn grenade")
  if not C:HasMarker("GolemStunned") then
    SpawnGrenade(C)
  end
end
function SpawnGrenade(C)
  local jointIndex = C:GetJointIndex("HeatGrenadeSpawnJoint")
  local jointPos = C:GetWorldJointPosition(jointIndex)
  local velocity = fwdGrenadeSpawnArc1
  if C:HasMarker("GolemMortarAttack") then
    local rand = math.random(1, #randGrenadeSpawnArcs)
    if rand == lastGrenadeArcIndex then
      repeat
        rand = math.random(1, #randGrenadeSpawnArcs)
      until rand ~= lastGrenadeArcIndex
    end
    lastGrenadeArcIndex = rand
    velocity = randGrenadeSpawnArcs[rand]
  else
    local rand = math.random(1, #fwdRandGrenadeSpawnArcs)
    velocity = fwdRandGrenadeSpawnArcs[rand]
  end
  local grenadeSpawnTemplate = {
    SpawnObject = "gogolemGrenade",
    HookName = "LuaHook_OnGrenadeCreated",
    OffsetPosition = jointPos,
    Velocity = velocity
  }
  C:SpawnGameObject(grenadeSpawnTemplate)
  grenadeSpawnCount = grenadeSpawnCount + 1
  if grenadeSpawnCount == grenadeHelpTextThresh and not grenadeInteract then
    ShowGrenadeHelpText()
  end
end
function LuaHook_OnGrenadeCreated(go, spawnedObject)
  print("Grenade created")
  global.grenade = spawnedObject
  spawnedObject:CallScript("LuaHook_SetParent", golemCreature)
end
function LuaHook_ShowCameraCollision(C, data)
  local camJoint = C:GetJointIndex("CameraCollision")
  if camJoint ~= nil then
    C:ShowJoint(camJoint)
  end
end
function LuaHook_HideCameraCollision(C, data)
  local camJoint = C:GetJointIndex("CameraCollision")
  if camJoint ~= nil then
    C:HideJoint(camJoint)
  end
end
function LuaHook_AggroEventGetAngleToHero(C, data)
  local player = game.Player.FindPlayer()
  if player ~= nil then
    global.aggroState = "INCOMBAT"
    local angleToPlayer = DL.FrontAngle(C, player)
    if -45 < angleToPlayer and angleToPlayer < 45 then
      return data:FindOutcomeBranchesEntry("Aggro0")
    elseif angleToPlayer <= -45 then
      return data:FindOutcomeBranchesEntry("Aggro120L")
    elseif 45 <= angleToPlayer then
      return data:FindOutcomeBranchesEntry("Aggro120R")
    end
  end
end
function LuaHook_CheckForStun(C, data)
  if C:MeterGetValue("StunState") >= 100 and not C:HasMarker("GolemStunned") and not C:IsDoingSyncMove() and C.HitPoints > 0 then
    if C:HasMarker("GolemMortarAttack") then
      C:ForceMove("BRA_HitCrumpleMortarPose")
    else
      C:ForceMove("BRA_HitCrumpleStandingPose")
    end
  end
end
function LuaHook_RageGrabTextShow(C, data)
  if not rageGrabTextShow then
    rageGrabTextShow = true
    uiCalls.SendSidebarDesignerMessage({
      Text = 40867,
      AdvanceType = uiCalls.msgParam.INFINITE_TIMER
    })
  end
end
function LuaHook_RageGrabTextHide(C, data)
  if rageGrabTextShow then
    uiCalls.UI_Event_TurnOffDesignerMessage()
    rageGrabTextShow = false
  end
end
function LuaHook_ShowCoreCollision(C, data)
  if global.coreJointIndex ~= nil and isCoreHidden == true then
    isCoreHidden = false
    C:ShowJoint(global.coreJointIndex)
  end
end
function LuaHook_HideCoreCollision(C, data)
  if global.coreJointIndex ~= nil and isCoreHidden == false then
    isCoreHidden = true
    C:HideJoint(global.coreJointIndex)
  end
end
function LuaHook_SetNormalDTree(C, data)
  global.DTree = "DTR_GOLEM_OFFENSIVE"
end
function LuaHook_SetStunnedDTree(C, data)
  global.DTree = "DTR_GOLEM_STUNNED"
end
function LuaHook_GolemDropHealthConsumable(ai, data)
  local chance = ai:LookupFloatConstant("GOLEM_RAGE_PUNCH_LOOT_CHANCE")
  if chance < math.random() then
    return
  end
  local index = ai:GetJointIndex("JOHead1")
  local pos = ai:GetWorldJointPosition(index)
  local dir = ai:GetWorldForward()
  pos = pos + dir * math.random(0.15, 0.5)
  local spawnArgs = {
    SpawnObject = "golootGenericHealthRune",
    OffsetPosition = pos,
    Level = game.Level.GetPermLevel()
  }
  game.Player.FindPlayer():CallScript("LuaHook_SpawnGameObject", spawnArgs)
end
