LD = require("design.LevelDesignLibrary")
DL = require("design.DesignerLibrary")
monitors = require("level.MonitorLibrary")
timers = require("level.timer")
color = require("core.color")
local camCollisionCheck = require("camera.collisioncheck")
uiCalls = require("ui.uicalls")
local CCOS = require("camera.camera_oneshot")
local checkpoint = require("level.checkpoint")
local CSL = require("camera.shakelibrary")
local PeakDragonModule = require("combat.PeakDragonModule")
local BossEncounter = require("boss.statemachine")
local ND = require("design.NarrativeDesignLibrary")
local actor = require("narrative.actor")
local heroPuppeteer, kratosActor, thisLevel, player
local warpoffset = engine.Vector.New(2, 0, 2)
ElevatorCollision = nil
slidingDoor2Breakable = nil
local dragonStageObjs = {}
local dragonActor
local dragonDefaultHealth = 2000
local DragonHealthMonitor
local goSpawnerName = "SyncScriptGroup"
local goRefJointName = "Phase1ElevatorSyncJoint"
local syncName = "Elevator_SyncStart"
local HiddenIntroStart = BossEncounter:AddStage("HiddenIntroStart")
local HiddenIntroPrep = BossEncounter:AddStage("HiddenIntroPrep")
local HiddenIntro = BossEncounter:AddStage("HiddenIntro")
local GrabMelee = BossEncounter:AddStage("GrabMelee")
local DragonExit = BossEncounter:AddStage("DragonExit")
local SmashFace = BossEncounter:AddStage("SmashFace")
function HiddenIntroStart:OnEnter(level, debugSkip)
  local l_level = game.FindLevel("Peak380_BigElevator")
  GameObjects.CollisionWall_Disable:ShowCollision()
  GameObjects.CollisionWallsDragon:HideCollision()
  if player.GroundLevel == nil and player.GroundLevel ~= l_level then
    return
  end
  timers.StartLevelTimer(0.5, function()
    WarpPlayerToElevator()
  end)
end
function HiddenIntroPrep:OnEnter(level)
  HiddenIntro_KratosSync()
  PeakDragonModule.ResetMomentum()
end
function HiddenIntroPrep:OnUpdate(level)
  if player:IsPlayingMove("MOV_DragonBreathEnterA") and player:GetActiveMovePercent() >= 0.99 then
    BossEncounter:ForwardState()
  end
end
function HiddenIntro:OnEnter(level)
  GameObjects.CamZone_DragonArena380:ShowCameraVolume()
  timers.StartLevelTimer(0.1, function()
    PeakDragonModule.ForceAllHudOff()
  end)
  timers.StartLevelTimer(0.11, function()
    player:MeterSetValue("Health", player:MeterGetMax("Health"))
  end)
  GameObjects.Peak380_Banter.LuaObjectScript.HelloDragon_Intro_Banter()
  level:CallScript("StartBraziersAnimLoop")
end
function HiddenIntro:OnUpdate(level)
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor:IsPlayingMove("MOV_DragonBreathEnterB") and l_dragonActor:GetActiveMovePercent() >= 1 then
    BossEncounter:ForwardState()
  end
end
local dragonIntroBookmarkStored = false
function GrabMelee:OnEnter(level)
  GameObjects.CollisionWallsDragon:ShowCollision()
  GameObjects.DeathPlane06:Show()
  PeakDragonModule.ForceAllHudOnNoCompass()
  PeakDragonModule.ToggleMeterBarVis(true)
  if not dragonIntroBookmarkStored then
    dragonIntroBookmarkStored = true
    local bookmarks = require("design.Bookmarks")
    local tableEntry = bookmarks["BOOKMARK_" .. "09_PeaksPass_035_DragonReveal"]
    game.World.StoreCheckpointAndBookmark(tableEntry)
  end
  game.Combat.TurnOnAndLockCombatStatus()
  player:CallScript("LuaHook_DisableRevive", true)
end
function GrabMelee:OnUpdate(level)
  SubmitDragonCameraElevator()
end
function GrabMelee:OnExit(level)
  GameObjects.CollisionWallsDragon:HideCollision()
  game.Combat.UnlockCombatStatus()
  game.Audio.SetBanterFact("GlobalEncEndCD", "True", 200)
  player:CallScript("LuaHook_DisableRevive", false)
end
function DragonExit:OnEnter(level)
  GrabExit_KratosSync()
  PeakDragonModule.ForceAllHudOff()
  PeakDragonModule.ToggleMeterBarVis(false)
  CSL.PlayShake("FFB_GENERIC_HIT_SMALL", 0.1, 0, 1)
  CSL.PlayShake("FSE_SHAKE_GENERIC_LARGE", 1.2, 0, 0.2)
  PeakDragonModule.ResetMomentum()
end
function SmashFace:OnEnter(level)
  DragonTunnelBreak()
  GameObjects.CamZone_DragonArena380:HideCameraVolume()
  GameObjects.CollisionWall_Disable:HideCollision()
  _G.SCA_DragonTurret_Disable()
  game.Audio.SetBanterFact("GlobalEncEndCD", "True", 200)
end
function SmashFace:OnExit(level)
  PeakDragonModule.ForceAllHudOn()
  PeakDragonModule.ToggleMeterBarVis(false)
end
local dragonStateData = {
  Init = {
    transitionHealth = 999.9,
    BRAname = "BRA_sg1_DragonHiddenIdle"
  },
  HiddenIntroStart = {
    transitionHealth = 999.9,
    BRAname = "BRA_sg1_csDragonElectricBreath_Start",
    sonBRA = "BRA_sg1_csDragonElectricBreath_Start",
    propName = "DragonElevator",
    propAnim = "stg1_intro"
  },
  HiddenIntroPrep = {
    transitionHealth = 999.9,
    BRAname = "BRA_DragonBreathEnterA",
    propName = "DragonElevator",
    propAnim = "csDragonElectricBreath_PartA"
  },
  HiddenIntro = {
    transitionHealth = 999.9,
    BRAname = "BRA_sg1_csDragonElectricBreath_Intro",
    heroBRA = "BRA_sg1_csDragonElectricBreath_Intro",
    sonBRA = "BRA_sg1_csDragonElectricBreath_Intro",
    propName = "DragonElevator",
    propAnim = "csDragonElectricBreath_PartB"
  },
  GrabMelee = {
    transitionHealth = 85,
    BRAname = "BRA_sg1_csDragonGrabIdle",
    propName = "DragonElevator",
    propAnim = "csDragonGrabIdle"
  },
  DragonExit = {
    transitionHealth = 999.9,
    BRAname = "BRA_sg1_csDragonGrabExit",
    propName = "DragonElevator",
    propAnim = "csDragonGrabExit"
  },
  SmashFace = {
    stageName = "SMASH FACE",
    transitionHealth = 999.9,
    BRAname = "BRA_sg1_csSmashDragonFace",
    propName = "DragonElevator",
    propAnim = "csSmashDragonFace"
  }
}
function BossEncounter:OnEnter(level)
  if dragonActor ~= nil then
    SyncDragonToArena()
  end
end
function BossEncounter:OnUpdate(level)
end
function BossEncounter:OnExit(level)
end
function OnScriptLoaded(level)
  player = game.Player.FindPlayer()
  thisLevel = level
  PeakDragonModule.SetupBossEncounter(BossEncounter)
  if dragonActor ~= nil then
    dragonActor:SetCombatTarget(player)
  end
end
function OnStart(level)
  spawnDragonBoss()
  dragonActor:SetCharacterConfig("pristineHead")
end
function OnUpdate(level)
  if player:IsInsideEntityZone("Zone_DebugSonWarp") then
    game.AI.FindSon():Warp(player:GetWorldPosition() + warpoffset, player:GetWorldForward())
  end
  if game.World.IsInsideCameraZone(player.WorldPosition, "CamZone_DragonArena380") then
    SubmitDragonCameraElevator()
  end
  PeakDragonModule.DragonHealthMonitor_OnUpdate()
end
function OnUseWorld(level)
end
function OnSaveCheckpoint(level)
  return {
    levelstate = checkpoint.Save(),
    dragonIntroBookmarkStored = dragonIntroBookmarkStored
  }
end
function OnRestoreCheckpoint(level, savedInfo)
  if dragonActor == nil and BossEncounter:GetBoss() == nil then
    dragonActor = FindEarthDragon()
    if dragonActor ~= nil then
      BossEncounter:AddBoss(dragonActor)
    end
  end
  dragonIntroBookmarkStored = savedInfo.dragonIntroBookmarkStored
  checkpoint.Restore(savedInfo.levelstate)
end
function CheckPoint()
  print("SAVING CHECKPOINT!")
  game.World.StoreCheckpoint()
end
function SetElevatorAtTunnelEntrance()
  local l_propObj = thisLevel:GetGameObject("dragonelevator00")
  l_propObj:ClearAllAnimCallbacks()
  l_propObj:StartAnim("csSmashDragonFace")
  l_propObj:JumpAnimToPercent(1)
end
function ForwardBossState()
  BossEncounter:ForwardState()
end
function LuaHook_ElevatorStoppedMelee(ai, data)
  print("Platform stopped!")
end
function LuaHook_ElevatorStoppedElectricBreath(ai, data)
  print("Platform stopped!")
  game.World.StoreCheckpoint()
end
function LuaHook_PushOffElevatorStart(ai, data)
  print("TnF Start")
  dragonActor:TriggerMoveEvent("LE_EarthDragon_PushOffElevatorStart")
  player:TriggerMoveEvent("LE_EarthDragon_PushOffElevatorStart")
end
function LuaHook_SmashFaceWin(ai, data)
  print("Win TnF")
  BossEncounter:SetActiveState("SmashFace")
end
function LuaHook_DamageHealthBar(ai, data)
  PeakDragonModule.DamageHealthBar()
end
function SetIntialMeterValues()
  local l_curHealth = dragonActor:MeterGetValue("DragonBossHealth")
  local l_curShield = dragonActor:MeterGetValue("DragonBossShield")
  dragonActor:MeterSetValue("DragonBossHealth_Hidden", 100)
  dragonActor:MeterSetValue("DragonBossHealth", math.abs(l_curHealth - 1.0E-5))
  dragonActor:MeterSetValue("DragonBossHealth", 100)
  dragonActor:MeterSetValue("DragonBossShield", math.abs(l_curShield - 1.0E-5))
  dragonActor:MeterSetValue("DragonBossShield", 100)
end
function DragonDebug()
  GameObjects.DragonModel1_AttackElevator:PlayAnimToEnd(0.5)
end
function BossEncounter_SetActiveState(statename)
  BossEncounter:SetActiveState(statename)
end
function DragonTunnelBreak()
  local peak500 = game.FindLevel("peak500_ChimneyTop")
  peak500:CallScript("DragonTunnelBreak")
end
function DisableDungeonDoor()
  GameObjects.dungeon_door_break:Hide()
  GameObjects.dungeon_door_break:HideCollision()
end
function StartDragonBossElevatorStages()
  print("START THE ACTUAL DRAGON FIGHT")
  GameObjects.DragonElevator:ShowCollision()
  BossEncounter:SetActiveState("HiddenIntroPrep")
end
function DestroyBreakables()
  for _, child in pairs(slidingDoor2Breakable.Children) do
    if child:IsBreakable() then
      local breakable = child:GetBreakable()
      breakable:Break()
      break
    end
  end
end
function WarpPlayerToElevator()
  local l_level = game.FindLevel("Peak380_BigElevator")
  local l_obj = l_level:GetGameObject("dragonelevator00")
  local l_jointIndex = l_obj:GetJointIndex("JOPelvis1")
  local l_jointPosition = l_obj:GetWorldJointPosition(l_jointIndex)
  local l_warpoffset = engine.Vector.New(0, 1, 0)
  local l_player = game.Player.FindPlayer()
  l_player:Warp(l_jointPosition + l_warpoffset, l_player:GetWorldJointForward(l_player:GetJointIndex("zeroJoint")))
end
function FindEarthDragon()
  return PeakDragonModule:FindEarthDragon()
end
function SyncDragonToArena()
  PeakDragonModule.SyncDragonToArena(thisLevel, goSpawnerName, syncName, dragonStateData, goRefJointName)
end
function InitHealthMontior()
  PeakDragonModule.InitHealthMontior(dragonStateData, dragonDefaultHealth)
end
function spawnDragonBoss()
  if dragonActor == nil then
    BossEncounter:AddCreature("BossDragonSpawner")
    if FindEarthDragon() == nil then
      BossEncounter:SpawnBoss()
    end
    dragonActor = FindEarthDragon()
  end
end
function isBossStateGrabMelee()
  local l_currentState = BossEncounter:GetActiveStateName()
  if l_currentState == "GrabMelee" then
    return true
  else
    return false
  end
end
function GrabExit_KratosSync()
  kratosActor = actor.Actor.New("Kratos", game.Player.FindPlayer)
  local seq = LD.CreateCineSequence(thisLevel, GameObjects.SyncScriptGroup, "sg1_csDragonGrabExit_Seq")
  seq:ActorSync(kratosActor, {
    Branch = "BRA_sg1_csDragonGrabExit",
    ReferenceJoint = "Phase1ElevatorSyncJoint",
    ReferenceJointOn = 1
  })
  seq:StartSequence()
end
function HiddenIntro_KratosSync()
  kratosActor = actor.Actor.New("Kratos", game.Player.FindPlayer)
  local seq = LD.CreateCineSequence(thisLevel, GameObjects.SyncScriptGroup, "csDragonElectricBreath_PartA_Seq")
  seq:ActorSync(kratosActor, {
    Branch = "BRA_DragonBreathEnterA",
    ReferenceJoint = "Phase1ElevatorSyncJoint",
    ReferenceJointOn = 1
  })
  seq:Do(HiddenIntroCamera_AltAngle)
  seq:StartSequence()
end
function SubmitDragonCameraElevator()
  game.Camera.SubmitCameraByName("CBT_EarthDragon_Base_Elevator")
  if dragonActor:HasMarker("DRAGONGRABBITE") or dragonActor:HasMarker("DRAGONGRABCLAW") then
    game.Camera.SubmitCameraByName("CBT_EarthDragon_Tell_Base_Elevator")
  end
end
function HiddenIntroCamera_AltAngle()
  local playerAngle
  local playerForward = player:GetWorldForward()
  local cameraWorldSpaceForward = engine.Vector.New(0, 0, -1)
  print("PLAYER FWD: ", playerForward)
  playerAngle = VectorToAngle(playerForward)
  print("PLAYER ANGLE ", playerAngle)
  local playerAngleInCameraSpace = DL.GetAngleBetweenVector(playerForward, cameraWorldSpaceForward)
  print("PLAYER IN CAMERA: ", playerAngleInCameraSpace)
  if 5 < playerAngleInCameraSpace and playerAngleInCameraSpace < 50 then
    local overrideCsCamLookUp = {
      Animation = "csDragonElectricBreath_PartA_Alt045",
      IgnoreCollision = 1,
      TweenIn = {
        Time = 0.8,
        EaseIn = 0,
        EaseOut = 1
      },
      TweenOut = {
        Time = 0.5,
        EaseIn = 1,
        EaseOut = 1
      },
      Priority = 995,
      SynchJoint = "camJoint"
    }
    game.Camera.StartCamera(overrideCsCamLookUp)
  end
end
function VectorToAngle(v)
  return math.atan2(v.z, v.x)
end
