local LD = require("design.LevelDesignLibrary")
local thisObj, thisLevel, player, son, deadObject
local lookWaitTime = 0
local cycleCount = 0
local walkCycleRate = 1
local zoneObjCount, axeContributing
local bladesContributing = false
local enableZoneObjectCount = true
local headerWalk = "helHeimDead00Walk0"
local animState = {}
local loopAnimName, lookAnimName, configName
local debugIndex = 0
local debugAnimName = ""
local debugTimer
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  SetZoneObjectCount()
  deadObject = thisObj:FindSingleGOByName("_deadObject_")
  if deadObject.IsRefNode then
    deadObject = deadObject.Child
  end
  animState.walkLoop = thisObj:FindLuaTableAttribute("StartAnim")
  animState.look = thisObj:FindLuaTableAttribute("LookAnim")
  lookWaitTime = thisObj:FindLuaTableAttribute("LookWaitTime")
  walkCycleRate = thisObj:FindLuaTableAttribute("WalkCycleRate")
  SelectWalk()
  SelectLook()
  SetConfig()
  game.SubObject.SetEntityZoneHandler(thisObj, thisObj)
  game.SubObject.Sleep(obj)
  game.SubObject.SetForgetOnCheckpoint(obj)
  SoundInit()
end
function SetZoneObjectCount()
  zoneObjCount = 0
  axeContributing = false
  CheckIfObjectIsInZone(player)
  CheckIfObjectIsInZone(player.Axe)
  CheckIfObjectIsInZone(son)
end
function CheckIfObjectIsInZone(obj)
  if obj and obj:IsInsideEntityZone(thisObj) then
    if obj == player.Axe then
      if IsAxeInFlight() == false then
        return
      else
        axeContributing = true
      end
    end
    zoneObjCount = zoneObjCount + 1
  end
end
function SelectWalk()
  if animState.walkLoop == "Random" then
    loopAnimName = headerWalk .. tostring(math.random(1, 3))
  else
    loopAnimName = "helHeimDead00" .. animState.walkLoop
  end
end
function SelectLook()
  if animState.look == "Random" then
    local tempList = {"LookL", "LookR"}
    lookAnimName = loopAnimName .. tempList[math.random(1, 2)]
  else
    lookAnimName = loopAnimName .. animState.look
  end
end
function SetConfig()
  configName = "helheimDead0" .. tostring(math.random(0, 5))
  deadObject:SetCharacterConfig(configName)
end
function OnStart(level, obj)
  PlayWalk()
end
function PlayWalk()
  debugAnimName = loopAnimName
  deadObject:JumpAnimToFrame(0)
  deadObject:StartAnim(loopAnimName)
  deadObject:SetAnimRate(walkCycleRate)
  deadObject:OnAnimDone(thisObj, "WalkCycleDone")
end
function WalkCycleDone()
  deadObject:ClearAllAnimCallbacks()
  if cycleCount >= lookWaitTime then
    cycleCount = 0
    PlayLook()
  else
    cycleCount = cycleCount + 1
    PlayWalk()
  end
end
function PlayLook()
  SelectLook()
  debugAnimName = lookAnimName
  deadObject:StartAnim(lookAnimName)
  deadObject:SetAnimRate(walkCycleRate)
  deadObject:OnAnimDone(thisObj, "LookDone")
end
function LookDone()
  deadObject:ClearAllAnimCallbacks()
  PlayWalk()
end
function Appear()
  PlayGhostAppearSound()
  deadObject:StartMaterialAnim("appear")
  deadObject:ShowParticleEmitter()
end
function Disappear()
  deadObject:StartMaterialAnim("disappear")
  deadObject:HideParticleEmitter()
end
function DisappearWithFade()
  PlayGhostDissolveSound()
  game.FX.Spawn("heldead_fade", thisLevel, {
    GameObject = deadObject,
    Joint = "JOBack2",
    AutoDelete = true
  })
  Disappear()
end
function DisappearWithBurst()
  PlayGhostDissolveSound()
  game.FX.Spawn("heldead_burst", thisLevel, {
    GameObject = deadObject,
    Joint = "JOBack2",
    AutoDelete = true
  })
  Disappear()
end
function IncrementZoneObjCount(objType)
  if enableZoneObjectCount == false then
    return
  end
  if zoneObjCount == 0 then
    if objType == "Character" then
      DisappearWithFade()
    elseif objType == "Axe" then
      DisappearWithBurst()
    end
  end
  zoneObjCount = zoneObjCount + 1
end
function DecrementZoneObjCount(objType)
  if enableZoneObjectCount == false then
    return
  end
  zoneObjCount = zoneObjCount - 1
  if zoneObjCount < 0 then
    zoneObjCount = 0
  end
  if zoneObjCount == 0 then
    Appear()
  end
end
function EnableZoneObjectCount()
  enableZoneObjectCount = true
  thisObj:ShowEntityVolume()
end
function DisableZoneObjectCount()
  enableZoneObjectCount = false
  thisObj:HideEntityVolume()
end
function IsAxeInFlight()
  if player.Axe.ThrowOutStatus == tweaks.tThrowOutStatus.eThrownWeaponStatus.kTOSInFlightOut or player.Axe.ThrowOutStatus == tweaks.tThrowOutStatus.eThrownWeaponStatus.kTOSInFlightReturn or player.Axe.ThrowOutStatus == tweaks.tThrowOutStatus.eThrownWeaponStatus.kTOSFalling then
    return true
  end
  return false
end
local bladeThrowOutStatus = {
  [tweaks.tThrowOutStatus.eThrownWeaponStatus.kTOSInFlightOut] = true,
  [tweaks.tThrowOutStatus.eThrownWeaponStatus.kTOSInFlightReturn] = true
}
function IsBladesInFlight()
  for weapon in player:IterateActiveWeapons() do
    if weapon ~= nil and weapon.Weapon ~= nil and weapon.Weapon:GetName() == "explosive00" and bladeThrowOutStatus[weapon.Weapon.ThrowOutStatus] then
      return true
    end
  end
  return false
end
function OnMarkerEnterZone(level, obj, volumeGameObject, markerGameObject, markerId)
  if IsPlayer(markerGameObject, markerId) or IsSon(markerGameObject, markerId) then
    IncrementZoneObjCount("Character")
  elseif IsAxe(markerGameObject, markerId) and IsAxeInFlight() then
    IncrementZoneObjCount("Axe")
    axeContributing = true
  elseif IsBlades(markerGameObject, markerId) and IsBladesInFlight() and bladesContributing == false then
    IncrementZoneObjCount("Axe")
    bladesContributing = true
  end
end
function OnMarkerExitZone(level, obj, volumeGameObject, markerGameObject, markerId)
  if IsPlayer(markerGameObject, markerId) or IsSon(markerGameObject, markerId) then
    DecrementZoneObjCount()
  elseif IsAxe(markerGameObject, markerId) and axeContributing == true then
    DecrementZoneObjCount()
    axeContributing = false
  elseif IsBlades(markerGameObject, markerId) and bladesContributing == true then
    DecrementZoneObjCount()
    bladesContributing = false
  end
end
function IsPlayer(markerGameObject, markerId)
  return markerGameObject == player and (game.LargeInteger.HashString(3) == markerId or game.LargeInteger.HashString(3) == game.LargeInteger.HashString(tostring(markerId)))
end
function IsAxe(markerGameObject, markerId)
  return markerGameObject == player.Axe
end
function IsBlades(markerGameObject, markerId)
  return markerGameObject:GetName() == "explosive00"
end
function IsSon(markerGameObject, markerId)
  return markerGameObject == son and (game.LargeInteger.HashString(5) == markerId or game.LargeInteger.HashString(5) == game.LargeInteger.HashString(tostring(markerId)))
end
function Debug_PlayNext_Walk()
  if debugIndex + 1 > 3 then
    debugIndex = 0
  end
  debugIndex = debugIndex + 1
  debugAnimName = headerWalk .. tostring(debugIndex)
  deadObject:StartAnim(debugAnimName)
end
function Debug_PlayNext_WalkLook()
  local walkLookAnims = {
    "1LookL",
    "2LookL",
    "3LookL",
    "1LookR",
    "2LookR",
    "3LookR"
  }
  if debugIndex + 1 > #walkLookAnims then
    debugIndex = 0
  end
  debugIndex = debugIndex + 1
  debugAnimName = headerWalk .. walkLookAnims[debugIndex]
  deadObject:StartAnim(debugAnimName)
end
function Debug_PlayAll_Walk()
  Debug_PlayNext_Walk()
  deadObject:OnAnimDone(thisObj, "Debug_PlayAll_Walk")
end
function Debug_PlayAll_WalkLook()
  Debug_PlayNext_WalkLook()
  deadObject:OnAnimDone(thisObj, "Debug_PlayAll_WalkLook")
end
function ShowDebugText()
  local debugText = "" .. [[

 AnimPlaying: ]] .. debugAnimName .. [[

 Frame: ]] .. deadObject.AnimFrame .. "/" .. deadObject.AnimLengthFrames .. [[

 cycleCount: ]] .. cycleCount .. [[

 walkCycleRate: ]] .. tostring(walkCycleRate) .. [[

 zoneObjCount: ]] .. tostring(zoneObjCount) .. [[

 axeContributing: ]] .. tostring(axeContributing) .. [[

 bladesContributing: ]] .. tostring(bladesContributing)
  local color = require("core.color")
  engine.DrawTextInWorld(thisObj:GetWorldPosition(), debugText, color.white)
end
local SNDGhost
function SoundInit()
  SNDGhost = thisObj:FindSingleSoundEmitterByName("SNDHelheimDead")
end
function PlayGhostDissolveSound()
  engine.Print("Playing Dissolve Sound")
  LD.PlaySound(SNDGhost, "SND_AMB_EMIT_Helheim_Dead_Vanish")
end
function PlayGhostAppearSound()
  engine.Print("Playing Appear Sound")
  LD.PlaySound(SNDGhost, "SND_AMB_EMIT_Helheim_Dead_Appear")
end
