local timer = require("level.timer")
local LD = require("design.LevelDesignLibrary")
local DL = require("design.DesignerLibrary")
local bboardUtil = require("game.BlackboardUtil")
local summonedGO, collisionSphere, collisionSphereScript
local state = "spawnFirst"
local counter = 0
local beam, chargeEffect
local chargeSize = 1
local chargeSizeSpeed = 2
local beamTip, beamCollision, spawnfx, spawnfx2
local spawnedIn = false
local arrowTypeIsLight = true
local upgradeLevel = 3
local rumbleParams = {EffectName = "FFB_MEDIUM", Duration = 0.3}
local shakeParams = {
  EffectName = "FSE_shake_Temp_Generic_Giant",
  Duration = 0.3
}
local tempTimer = 0
local unitTime
local genericCounter = 0
function LuaHook_DragonSummon(level, go, spawnedObject)
  summonedGO = spawnedObject
  summonedGO:ShowJoint(summonedGO:GetJointIndex("dragon_stream"))
  state = "spawn"
  spawnedIn = true
  local cameraForward = game.Camera.GetOrbitForward()
  cameraForward.y = 0
  summonedGO:SetWorldPosition(game.Player.FindPlayer().WorldPosition)
  summonedGO:SetWorldFacing(game.Player.FindPlayer():GetWorldForward())
  upgradeLevel = game.Wallets.GetResourceValue("HERO", "SummonDragon_res")
  local hero = game.Player.FindPlayer()
  if hero:PickupIsAcquired("SummonDragon") then
    upgradeLevel = hero:PickupGetStage("SummonDragon") + 1
  end
  if upgradeLevel == nil or upgradeLevel <= 0 then
    upgradeLevel = 1
  end
end
function OnScriptLoaded(level, go)
  local spawnTemplate = {
    SpawnObject = "godragon01",
    HookName = "LuaHook_DragonSummon",
    Level = level,
    OffsetPosition = game.Player.FindPlayer().WorldPosition - engine.Vector.New(0, -1000, 0)
  }
  go:SpawnGameObject(spawnTemplate)
end
function AutoBranch(gameobject, params)
  if gameobject.AnimPercent >= params.On then
    gameobject:StartMaterialAnim(params.AnimName)
    return true
  end
  return false
end
function OnUpdate(level, go)
  unitTime = level:GetUnitTime()
  if state == "done" then
    return
  end
  if summonedGO == nil then
    return
  end
  local player = game.Player.FindPlayer()
  local indexBeam = summonedGO:GetJointIndex("JOJaw1")
  counter = counter + 1
  if 2 <= counter and spawnedIn then
    summonedGO:SetScale(0.1)
  end
  if state == "spawn" then
    summonedGO:StartMaterialAnim("attSwoopBreathEnter")
    summonedGO:ShowJoint(summonedGO:GetJointIndex("dragon_stream"))
    state = "spawnExplosion"
    game.FX.SubmitEffect(rumbleParams)
    game.FX.SubmitEffect(shakeParams)
  elseif state == "spawnExplosion" then
    if summonedGO.AnimPercent >= 0.02 then
      state = "spawnIntro"
      local concussionParams = {}
      local jointIndex = summonedGO:GetJointIndex("JONeck1")
      concussionParams.WorldLocation = summonedGO:GetWorldJointPosition(jointIndex)
      concussionParams.Creature = game.AI.FindSon()
      concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
      concussionParams.Tweak = "CNC_LIGHT_DRAGON_EXPLOSION"
      game.Combat.PlayConcussion(concussionParams)
      genericCounter = 0
    end
  elseif state == "spawnIntro" then
    if genericCounter == 0 then
      if summonedGO.AnimPercent >= 0.9 then
        genericCounter = 1
        spawnfx = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
        spawnfx:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      end
    elseif genericCounter == 1 then
      spawnfx:SetScale(4)
      genericCounter = 2
      tempTimer = 0
    elseif genericCounter == 2 then
      tempTimer = tempTimer + unitTime
      if 0.05 <= tempTimer then
        summonedGO:HideJoint(summonedGO:GetJointIndex("dragon_stream"))
        genericCounter = 3
      end
    end
    if 1 <= summonedGO.AnimPercent then
      state = "spawnIntroTransition"
      genericCounter = 0
      tempTimer = 0
    end
  elseif state == "spawnIntroTransition" then
    spawnfx:SetScale(4)
    if 0.75 <= tempTimer and genericCounter == 0 then
      summonedGO:StartMaterialAnim("attSwoopBreathLoop")
      genericCounter = 1
    elseif genericCounter == 1 then
      state = "fire1_Start"
      summonedGO:ShowJoint(summonedGO:GetJointIndex("dragon_stream"))
      spawnfx2 = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
      local jointIndex = summonedGO:GetJointIndex("JONeck1")
      spawnfx2:SetWorldPosition(summonedGO:GetWorldJointPosition(jointIndex))
      genericCounter = 0
    end
    tempTimer = tempTimer + unitTime
  elseif state == "fire1_Start" then
    if genericCounter == 0 then
      spawnfx2:SetScale(5)
      genericCounter = 1
      rumbleParams.Duration = 1
      shakeParams.Duration = 1
      game.FX.SubmitEffect(rumbleParams)
      game.FX.SubmitEffect(shakeParams)
    end
    if summonedGO.AnimPercent >= 0 then
      state = "fire1_TurnOnCollision"
      collisionSphere = game.FX.Spawn("dragon01Collision")
      collisionSphere:SetWorldPosition(summonedGO.WorldPosition + engine.Vector.New(0, 100, 0))
      chargeEffect = game.FX.Spawn("Electric_Ground_Shock", level)
      chargeEffect:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      beam = game.FX.Spawn("ElectricBreath_Beam_FX", level)
      beamTip = game.FX.Spawn("Electric_Ground_Shock", level)
    end
  elseif state == "fire1_TurnOnCollision" then
    state = "fire1"
    collisionSphereScript = collisionSphere:FindSingleGOByName("CombatCollisionManager")
    collisionSphereScript.LuaObjectScript.Enable()
    collisionSphereScript.LuaObjectScript.ChangeCombatCollisionType("SummonDragon_Beam_Collision")
  elseif state == "fire1" then
    if summonedGO.AnimPercent >= 0.45 then
      state = "fire1_end"
      beam:Destroy()
      beamTip:Destroy()
      chargeEffect:Destroy()
      collisionSphere:Destroy()
    else
      beam:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      local direction = -summonedGO:GetWorldJointForward(indexBeam)
      direction.y = 0
      local downward = (direction * 5 - engine.Vector.New(0, 0.7, 0)):Normalized()
      beam:SetWorldFacing(downward)
      beamTip:SetScale(2)
      local pos = summonedGO:GetWorldJointPosition(indexBeam)
      local dir = downward
      local collisionParams = {
        SourceGameObject = summonedGO,
        EntityType = game.CollisionType.New("kEnvironment"),
        RejectMaterialFlags = game.GroundType.New("kGT_CosmeticIK", "kGT_Death", "kGT_InstantDeath", "kGT_NoTargetThru")
      }
      local raycastFinalPos = pos + dir * 100
      local hit = game.World.RaycastCollision(pos, raycastFinalPos, collisionParams)
      if hit ~= nil then
        raycastFinalPos = hit.Position + engine.Vector.New(0, 0.5, 0)
      end
      beamTip:SetWorldPosition(raycastFinalPos)
      chargeEffect:SetWorldPosition(raycastFinalPos)
      collisionSphere:SetWorldPosition(raycastFinalPos)
    end
  elseif state == "fire1_end" then
    if 1 <= summonedGO.AnimPercent then
      if upgradeLevel == 1 then
        state = "poof"
        spawnfx = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
        spawnfx:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      else
        state = "fire1_endTransition"
        spawnfx = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
        spawnfx:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
        genericCounter = 0
        tempTimer = 0
      end
    end
  elseif state == "fire1_endTransition" then
    if genericCounter == 0 then
      spawnfx:SetScale(4)
      summonedGO:HideJoint(summonedGO:GetJointIndex("dragon_stream"))
      genericCounter = 1
    elseif genericCounter == 1 then
      if 0.3 <= tempTimer then
        summonedGO:StartMaterialAnim("attSwoopBreathLoop02")
        genericCounter = 2
      end
      tempTimer = tempTimer + unitTime
    elseif genericCounter == 2 then
      state = "fire2_Start"
      summonedGO:ShowJoint(summonedGO:GetJointIndex("dragon_stream"))
      spawnfx2 = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
      spawnfx2:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      genericCounter = 0
      tempTimer = 0
      game.FX.SubmitEffect(rumbleParams)
      game.FX.SubmitEffect(shakeParams)
    end
  elseif state == "fire2_Start" then
    if genericCounter == 0 then
      genericCounter = 1
      spawnfx2:SetScale(5)
    end
    if summonedGO.AnimPercent >= 0.05 then
      state = "fire2_TurnOnCollision"
      collisionSphere = game.FX.Spawn("dragon01Collision")
      collisionSphere:SetWorldPosition(summonedGO.WorldPosition + engine.Vector.New(0, 100, 0))
      chargeEffect = game.FX.Spawn("Electric_Ground_Shock", level)
      chargeEffect:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      beam = game.FX.Spawn("ElectricBreath_Beam_FX", level)
      beamTip = game.FX.Spawn("Electric_Ground_Shock", level)
    end
  elseif state == "fire2_TurnOnCollision" then
    state = "fire2"
    collisionSphereScript = collisionSphere:FindSingleGOByName("CombatCollisionManager")
    collisionSphereScript.LuaObjectScript.Enable()
    collisionSphereScript.LuaObjectScript.ChangeCombatCollisionType("SummonDragon_Beam_Collision")
  elseif state == "fire2" then
    if summonedGO.AnimPercent >= 0.38333333 then
      state = "fire2_end"
      beam:Destroy()
      beamTip:Destroy()
      chargeEffect:Destroy()
      collisionSphere:Destroy()
    else
      beam:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      local direction = -summonedGO:GetWorldJointForward(indexBeam)
      direction.y = 0
      local downward = (direction * 5 - engine.Vector.New(0, 0.7, 0)):Normalized()
      beam:SetWorldFacing(downward)
      beamTip:SetScale(2)
      local pos = summonedGO:GetWorldJointPosition(indexBeam)
      local dir = downward
      local collisionParams = {
        SourceGameObject = summonedGO,
        EntityType = game.CollisionType.New("kEnvironment"),
        RejectMaterialFlags = game.GroundType.New("kGT_CosmeticIK", "kGT_Death", "kGT_InstantDeath", "kGT_NoTargetThru")
      }
      local raycastFinalPos = pos + dir * 100
      local hit = game.World.RaycastCollision(pos, raycastFinalPos, collisionParams)
      if hit ~= nil then
        raycastFinalPos = hit.Position + engine.Vector.New(0, 0.5, 0)
      end
      beamTip:SetWorldPosition(raycastFinalPos)
      chargeEffect:SetWorldPosition(raycastFinalPos)
      collisionSphere:SetWorldPosition(raycastFinalPos)
    end
  elseif state == "fire2_end" then
    if 1 <= summonedGO.AnimPercent then
      if upgradeLevel < 3 then
        state = "poof"
        spawnfx = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
        spawnfx:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      else
        state = "fire2_endTransition"
        genericCounter = 0
        tempTimer = 0
        spawnfx = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
        spawnfx:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      end
    end
  elseif state == "fire2_endTransition" then
    if genericCounter == 0 then
      spawnfx:SetScale(5)
      summonedGO:HideJoint(summonedGO:GetJointIndex("dragon_stream"))
      genericCounter = 1
    elseif genericCounter == 1 then
      if 0.4 < tempTimer then
        summonedGO:StartMaterialAnim("attSwoopBreathEnterAlt01")
        genericCounter = 2
      end
      tempTimer = tempTimer + unitTime
    elseif genericCounter == 2 then
      spawnfx2 = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
      spawnfx2:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      genericCounter = 3
    elseif genericCounter == 3 then
      spawnfx2:SetScale(5)
      summonedGO:ShowJoint(summonedGO:GetJointIndex("dragon_stream"))
      state = "slamdown1"
    end
  elseif state == "fire3_Start" then
    state = "fire3"
  elseif state == "fire3" then
    state = "exit"
  elseif state == "exit" then
    state = "done"
  elseif state == "slamdown1" then
    if summonedGO.AnimPercent > 0.05 then
      state = "slamdown1_Trans"
      local concussionParams = {}
      local jointIndex = summonedGO:GetJointIndex("JOPelvis1")
      concussionParams.WorldLocation = summonedGO:GetWorldJointPosition(jointIndex)
      concussionParams.Creature = game.AI.FindSon()
      concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
      concussionParams.Tweak = "CNC_LIGHT_DRAGON_SLAMDOWN_EXPLOSION"
      game.Combat.PlayConcussion(concussionParams)
      game.FX.SubmitEffect(rumbleParams)
      game.FX.SubmitEffect(shakeParams)
      genericCounter = 0
    end
  elseif state == "slamdown1_Trans" then
    if genericCounter == 0 and summonedGO.AnimPercent > 0.49166667 then
      local concussionParams = {}
      local jointIndex = summonedGO:GetJointIndex("JOPelvis1")
      concussionParams.WorldLocation = summonedGO:GetWorldJointPosition(jointIndex)
      concussionParams.Creature = game.AI.FindSon()
      concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
      concussionParams.Tweak = "CNC_LIGHT_DRAGON_SLAMDOWN_EXPLOSION"
      game.Combat.PlayConcussion(concussionParams)
      game.FX.SubmitEffect(rumbleParams)
      game.FX.SubmitEffect(shakeParams)
      genericCounter = 1
    elseif genericCounter == 1 and 1 <= summonedGO.AnimPercent then
      state = "poof"
      spawnfx = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
      spawnfx:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
    end
  elseif state == "slamdown2" then
    if summonedGO.AnimPercent > 0.5 then
      state = "slamdown2_Trans"
      local concussionParams = {}
      local jointIndex = summonedGO:GetJointIndex("JOPelvis1")
      concussionParams.WorldLocation = summonedGO:GetWorldJointPosition(jointIndex)
      concussionParams.Creature = game.AI.FindSon()
      concussionParams.EnemyId = DL.HashCreatureID(game.Player.FindPlayer(), "SON00")
      concussionParams.Tweak = "CNC_LIGHT_DRAGON_SLAMDOWN_EXPLOSION"
      game.Combat.PlayConcussion(concussionParams)
    end
  elseif state == "slamdown2_Trans" then
    if 1 <= summonedGO.AnimPercent then
      spawnfx = game.FX.Spawn("SonTeleport_Enter", level, {AutoDelete = true})
      spawnfx:SetWorldPosition(summonedGO:GetWorldJointPosition(indexBeam))
      state = "poof"
    end
  elseif state == "poof" then
    state = "done"
    if spawnfx ~= nil then
      spawnfx2:SetScale(5)
    end
    if spawnfx2 ~= nil then
      spawnfx2:SetScale(5)
    end
    if summonedGO ~= nil then
      summonedGO:Destroy()
    end
    go:Destroy()
  end
end
