local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local monitors = require("level.MonitorLibrary")
local uiCalls = require("ui.uicalls")
local CCOS = require("camera.camera_oneshot")
local CSL = require("camera.shakelibrary")
local thisObj, thisLevel, player, son, gearPuzzleController, flip, drop, waterPlane, waterMonitor, trapCollision
local cameraType = 1
local bPlayWaterCamera = false
local goCamera
local bGearPuzzleSolved = false
local oneShotKickApproach010, oneShotKickApproach020
local bKnifeSacrificed = false
local bPlayerAttachedToCrank = false
local bTrapSprung = false
local sphereMonitor, sonPuppeteer, kraPuppeteer
local bDropping = false
local dropNumber = 0
local dropDelay = 11
local dropAmount = {
  25,
  15,
  12,
  9,
  8,
  8
}
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  flip = level:GetGameObject("FlipSwitch3")
  drop = level:GetGameObject("innerTrapFloor")
  waterPlane = level:GetGameObject("waterPlane")
  trapCollision = level:GetGameObject("trapCollision")
  gearPuzzleController = thisLevel:GetGameObject("gearPuzzle_control")
  SoundInit()
end
function OnFirstStart(level, obj)
  drop:JumpAnimToFrame(10)
  drop:PauseAnim()
  waterPlane:Hide()
end
function OnStart(level, obj)
  GameObjects.waterSplashes:Hide()
  HideDropFlowingWater()
  GameObjects.moveHereWhenAttached.LuaObjectScript.Disable()
  GameObjects.moveHereWhenDrop.LuaObjectScript.Disable()
  GameObjects.moveHereAndRead.LuaObjectScript.Disable()
  GameObjects.moveHereWhenTrapped.LuaObjectScript.Disable()
  GameObjects.moveHereWhenInspect.LuaObjectScript.Disable()
  if bTrapSprung then
    GameObjects.waterTrapVines.LuaObjectScript.ReloadTrap()
    player:CallScript("LuaHook_DisableRevive", true)
  end
  if bDropping then
    HideFlowingWater()
    dropNumber = 0
    drop:JumpAnimationToFrame(220)
    drop:PauseAnimation()
    bPlayWaterCamera = true
    PlaySoundFloorWaterLapsLoop()
  end
  game.GameObject.AnimSync(GameObjects.mainspool, GameObjects.mechanism)
end
function OnUpdate(level, obj)
  if cameraType == 7 then
    game.Camera.SubmitCameraByName("ENV_Crank_KnifeSacrifice")
  elseif game.World.IsInsideCameraZone(player.WorldPosition, "CamZone_ChainedToCrank") then
    if bPlayWaterCamera == true then
      game.Camera.SubmitCameraByName("AIM_Cal500_WaterTrap_Trapped_Far_000")
      if drop.AnimFrame > 250 and drop.AnimFrame < 280 then
        game.Camera.SubmitCameraByName("AIM_Cal500_WaterTrap_Trapped_Far_000")
        game.Camera.SubmitCameraByName("AIM_Cal500_WaterTrap_Trapped_Far_010")
      elseif drop.AnimFrame > 280 then
        game.Camera.SubmitCameraByName("AIM_Cal500_WaterTrap_Trapped_Far_010")
        game.Camera.SubmitCameraByName("AIM_Cal500_WaterTrap_Trapped_Far_020")
      end
    elseif cameraType == 40 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_WaterTrap_Intro_010")
    elseif cameraType == 42 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_WaterTrap_Intro_010")
      game.Camera.SubmitCameraByName("PLYR_Cal500_WaterTrap_Intro_013")
    elseif cameraType == 46 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_WaterTrap_Intro_013")
      game.Camera.SubmitCameraByName("PLYR_Cal500_WaterTrap_Intro_014")
    elseif cameraType == 50 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_WaterTrap_Intro_015")
    elseif cameraType == 55 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_WaterTrap_Success_010")
    elseif cameraType == 60 then
      game.Camera.SubmitCameraByName("PLYR_PreRainingSpikes")
    elseif cameraType == 6 then
      game.Camera.SubmitCameraByName("PLYR_RainingSpikes_CAMSEQ")
    elseif cameraType == 8 then
      game.Camera.SubmitCameraByName("ENV_Crank_Cal500_Drowning")
    elseif cameraType == 110 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_SpikeTrap_005_Rising")
    elseif cameraType == 115 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_SpikeTrap_005_Rising")
      game.Camera.SubmitCameraByName("PLYR_Cal500_SpikeTrap_007_Kratos")
    elseif cameraType == 118 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_SpikeTrap_007_Kratos")
      game.Camera.SubmitCameraByName("PLYR_Cal500_SpikeTrap_008_Son")
    elseif cameraType == 120 then
      game.Camera.SubmitCameraByName("PLYR_Cal500_SpikeTrap_008_Son")
      game.Camera.SubmitCameraByName("PLYR_Cal500_SpikeTrap_010_Idle")
    end
  end
  if oneShotKickApproach010 ~= nil then
    oneShotKickApproach010:Update()
  end
  if oneShotKickApproach020 ~= nil then
    oneShotKickApproach020:Update()
  end
end
function CameraStartKickApproach010()
  oneShotKickApproach010 = CCOS.OneShotCamera.New("ENV_Vista_RuneDrop_010", 8, nil)
  oneShotKickApproach010:Start()
end
function CameraStartKickApproach020()
  oneShotKickApproach020 = CCOS.OneShotCamera.New("ENV_Vista_RuneDrop_020", 5, nil)
  oneShotKickApproach020:Start()
  oneShotKickApproach020:SetCallback(CameraDestroyKickApproach)
end
function CameraDestroyKickApproach()
  oneShotKickApproach010 = nil
  oneShotKickApproach020 = nil
end
function PlayGearsExplodingCamera()
  local csCamGearsExploding = {
    Animation = "envWaterTrapIdle_csCamGearsExplode",
    IgnoreCollision = 1,
    TweenIn = {
      Time = 0.8,
      EaseIn = 1,
      EaseOut = 1
    },
    TweenOut = {
      Time = 2.6,
      EaseIn = 1,
      EaseOut = 1
    },
    Priority = 900,
    SynchJoint = "camJoint"
  }
  game.Camera.StartCamera(csCamGearsExploding)
end
function OnSaveCheckpoint(level, obj)
  return {
    bPlayerAttachedToCrank = bPlayerAttachedToCrank,
    bGearPuzzleSolved = bGearPuzzleSolved,
    bTrapSprung = bTrapSprung,
    bDropping = bDropping,
    bPlayWaterCamera = bPlayWaterCamera,
    cameraType = cameraType
  }
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  bPlayerAttachedToCrank = savedInfo.bPlayerAttachedToCrank
  bGearPuzzleSolved = savedInfo.bGearPuzzleSolved
  bTrapSprung = savedInfo.bTrapSprung
  bDropping = savedInfo.bDropping
  bPlayWaterCamera = savedInfo.bPlayWaterCamera
  cameraType = savedInfo.cameraType
end
function AttachedToCrank()
  sphereMonitor = monitors.CreateAnimFrameMonitor(thisLevel:GetGameObject("mechanism"))
  sphereMonitor:OnFrameForward(100, function()
    GameObjects.Btr_WaterTrap.LuaObjectScript.PlayWolfTrap1()
  end)
  bPlayerAttachedToCrank = true
  flip.LuaObjectScript.SetDrivenObject(GameObjects.mechanism)
  GameObjects.moveHereWhenAttached.LuaObjectScript.Enable()
end
function DetachedFromCrank()
  sphereMonitor = nil
  bPlayerAttachedToCrank = false
end
function PuppetSonToCorner()
  sonPuppeteer = game.Puppeteer.New(thisObj, "moveSonToCorner", son)
  sonPuppeteer:Advertise("SON:AUTO")
  sonPuppeteer:OnEngaged(SonMoveToCorner)
end
function SonMoveToCorner()
  if sonPuppeteer ~= nil then
    sonPuppeteer:Approach({
      pos = LD.GetWorldJointPosition("sonPOI1", "son_wait"),
      dir = LD.GetWorldJointForward("sonPOI1", "son_wait"),
      speed = 6,
      stop = true
    })
    sonPuppeteer:OnArrival(UnPuppetSon, {
      pos = LD.GetWorldJointPosition("sonPOI1", "son_wait"),
      radius = 1
    })
  end
end
function UnPuppetSon()
  if sonPuppeteer ~= nil then
    sonPuppeteer:Clear()
    sonPuppeteer = nil
  end
end
function Klaxon()
  if bPlayerAttachedToCrank then
    son:CallScript("OnStandGround", true)
    waterPlane:Show()
    player:CallScript("LuaHook_DisableRevive", true)
    game.Compass.SetDesignerForcedHide(true)
    game.Player.FindPlayer().Pad:DisableGameButton(tweaks.ePad.kPadUp)
    son:SetNewAvailabilityRequest("LevelDesignScript", {AvailableForCombat = false})
    GameObjects.FlipSwitch3.LuaObjectScript.Lock()
    player:ForceOverrideLastWeapon("Bare")
    player:TriggerMoveEvent("kLEAutoExitForce")
    GameObjects.waterTrapVines.LuaObjectScript.StartTrap()
    LD.CallFunctionAfterDelay(function()
      son:CallScript("WarpAndReset", GameObjects.WarpSonForTrap:GetWorldPosition(), GameObjects.WarpSonForTrap:GetWorldForward())
    end, 3)
    drop:PlayAnimationToFrame(220)
    drop:OnAnimationDone(thisObj, "Drop1")
    trapCollision:ShowCollision()
    trapCollision:Show()
    UnPuppetSon()
    son:CallScript("EnterBehaviorContext", "PANIC_BEHAVIOR_CONTEXT_CONFIG")
    GameObjects.Btr_WaterTrap.LuaObjectScript.PlayWolfTrap1_Start()
    GameObjects.moveHereWhenAttached.LuaObjectScript.Disable()
    GameObjects.moveHereWhenTrapped.LuaObjectScript.Enable()
    GameObjects.FlipSwitch3:FindSingleGOByName("WheelCrank").LuaObjectScript.ClearDrivenObject()
    GameObjects.mechanism:PlayAnimationToFrame(0, {Rate = -2})
    GameObjects.WolvesDiscovered.LuaObjectScript.Disable()
    local stomperwad = game.FindLevel("Cal512_RuneVaultHalls2")
    stomperwad:CallScript("StopStomperHall")
    bTrapSprung = true
    GameObjects.sonContext_control.LuaObjectScript.DisableHint1()
    GameObjects.sonContext_control.LuaObjectScript.DisableHint2()
    GameObjects.sonContext_control.LuaObjectScript.DisableHint3()
    GameObjects.sonContext_control.LuaObjectScript.DisableBalconyHint()
    GameObjects.sonContext_control.LuaObjectScript.DisableCrackClimbHint()
    game.Audio.StartCheckpointedMusic("SND_MX_CAL_vault_puzzle_trap_1_in")
  end
end
function Drop1()
  GameObjects.waterSplashVFX:Show()
  ShowFlowingWater()
  ShowDropFlowingWater()
  local waterEndFrame = 110
  waterPlane:PlayAnimToFrame(waterEndFrame, 0.25)
  PlayWaterPourSoundToFrame(waterEndFrame)
  PlayWaterSplashSoundToFrame(waterEndFrame)
  waterPlane:OnAnimDone(thisObj, "HideFlowingWater")
  Splash()
  cameraType = 40
  GameObjects.dunkAnim:PlayAnimationToFrame(43)
  GameObjects.moveHereWhenTrapped.LuaObjectScript.Disable()
  GameObjects.moveHereWhenDrop.LuaObjectScript.Enable()
  PlaySoundFloorDrop01()
  PlaySoundFloorDrop01_Loop(43)
  flip.LuaObjectScript.PlayBGGearsSound()
end
function Splash()
  GameObjects.kratos_drop_splash:Show()
  GameObjects.kratos_drop_splash:JumpAnimationToPercent(0)
  GameObjects.kratos_drop_splash:PlayAnimationToEnd()
  timers.StartLevelTimer(2, function()
    GameObjects.kratos_drop_splash:Hide()
  end)
end
function KidRunsToDropSpot()
  TurnToLookAtPuzzle()
end
function TurnToLookAtPuzzle()
  GameObjects.Btr_WaterTrap.LuaObjectScript.PlayWolfTrap1_Start_01a()
  local covers = thisLevel:FindGameObjects("WaterTrap_Levers_*")
  for _, cover in ipairs(covers) do
    cover:PlayAnimToEnd()
  end
  PlaySoundLeverCoversOpen()
  CSL.PlayDefaultShake("VerticalSliding", 2, 0, 0)
  timers.StartLevelTimer(2, function()
    CSL.PlayShake("FSE_SHAKE_GENERIC_VERYSMALL", 0.35, 0.2, 0.3)
    CSL.PlayShake("FFB_GENERIC_HIT_SMALL", 0.35, 0, 0.5)
  end)
end
function ChangeCameraToRune()
  cameraType = 42
  timers.StartLevelTimer(0.5, SonInspectRunes)
end
function SonInspectRunes()
  GameObjects.moveHereWhenDrop.LuaObjectScript.Disable()
  GameObjects.moveHereAndRead.LuaObjectScript.Enable()
  GameObjects.Btr_WaterTrap.LuaObjectScript.PlayWolfTrap1_Start_01b()
end
function SonExplainHint()
  GameObjects.moveHereAndRead.LuaObjectScript.Disable()
  GameObjects.moveHereWhenInspect.LuaObjectScript.Enable()
  timers.StartLevelTimer(1.2, function()
    cameraType = 46
  end)
end
function StartPuzzle()
  LD.CompleteQuest("Quest_Caldera_Objective500")
  son:CallScript("ClearBehaviorContext")
  GameObjects.moveHereAndRead.LuaObjectScript.Disable()
  GameObjects.moveHereWhenInspect.LuaObjectScript.Disable()
  son:CallScript("OnStandGround", false)
  flip.LuaObjectScript.Disable()
  timers.StartLevelTimer(1, function()
    gearPuzzleController.LuaObjectScript.StartTrap()
  end)
  timers.StartLevelTimer(4, function()
    bPlayWaterCamera = true
  end)
end
function Drop2()
  bDropping = true
  GameObjects.waterSplashes:Show()
  Splash()
  waterMonitor = monitors.CreateAnimFrameMonitor(drop)
  waterMonitor:OnFrameForward(300, DrownKratos)
  local dropEndFrame = 300
  DropALittle()
  PlaySoundFloorDrop02()
  local waterEndFrame = 370
  waterPlane:PlayAnimToFrame(waterEndFrame, 0.125)
end
function DropALittle()
  if bDropping then
    Splash()
    CSL.PlayDefaultShake("ShakeRumbleSmall", 0.8)
    dropNumber = dropNumber + 1
    local newFrame = 0
    if dropNumber < #dropAmount then
      newFrame = drop.AnimFrame + dropAmount[dropNumber]
    else
      newFrame = drop.AnimFrame + 4
    end
    drop:PlayAnimToFrame(newFrame, 0.6)
    timers.StartLevelTimer(dropDelay, DropALittle)
    PlaySoundFloorDropTimed()
  end
end
function ReleaseTrap()
  bTrapSprung = false
  player:CallScript("LuaHook_DisableRevive", false)
  flip.LuaObjectScript.PlayUnTrapSound()
end
function ShowFlowingWater()
  local waterObjects = thisLevel:FindGameObjects("flowingWater*")
  for _, water in ipairs(waterObjects) do
    water:Show()
  end
end
function ShowDropFlowingWater()
  local waterObjects = thisLevel:FindGameObjects("dropFlowingWater*")
  for _, water in ipairs(waterObjects) do
    water:Show()
  end
end
function HideFlowingWater()
  local waterObjects = thisLevel:FindGameObjects("flowingWater*")
  for _, water in ipairs(waterObjects) do
    water:Hide()
  end
end
function HideDropFlowingWater()
  local waterObjects = thisLevel:FindGameObjects("dropFlowingWater*")
  print("HIDE FLOWING WATER")
  for _, water in ipairs(waterObjects) do
    water:Hide()
  end
end
function PauseDescent()
  drop:PauseAnimation()
  bGearPuzzleSolved = true
  bDropping = false
  waterMonitor = nil
end
function DrownKratos()
  if not bGearPuzzleSolved then
    son:CallScript("EnterBehaviorContext", "PANIC_BEHAVIOR_CONTEXT_CONFIG")
    GameObjects.moveHereWhenDrown.LuaObjectScript.Enable()
    bDropping = false
    drop:PauseAnim()
    GameObjects.gearPuzzle_control.LuaObjectScript.Cancel()
    GameObjects.waterTrapVines.LuaObjectScript.KillWithWater()
    timers.StartLevelTimer(4, function()
      GameObjects.Btr_WaterTrap.LuaObjectScript.PlayWolfTrap1_Fail()
      PlaySoundFloorDropTimed()
      PlaySoundOnDrown()
      GameObjects.drownAnim:PlayAnimationToEnd({Rate = 3})
      uiCalls.UI_Event_Fade_In(1)
    end)
  end
end
function SkewerKratos()
  GameObjects.waterTrapVines.LuaObjectScript.KillWithSpikes()
  GameObjects.spikeTrap_control.LuaObjectScript.PlaySoundOnSkewerKratos()
  timers.StartLevelTimer(1, function()
    uiCalls.UI_Event_Fade_To_Black(1)
  end)
end
function ReturnToNormalCamera()
  cameraType = 1
end
function StopWaterCamera()
  bPlayWaterCamera = false
end
function CameraGearPuzzleSuccess()
  cameraType = 55
end
function PrepareToLookUpAtSpikes()
  cameraType = 60
end
function LookUpAtSpikes()
  cameraType = 6
  timers.StartLevelTimer(10.1, SetSpikePlatformRisingCamera)
end
function SetSpikePlatformRisingCamera()
  cameraType = 110
end
function SetSpikeKratosCamera()
  cameraType = 115
end
function SetSpikeSonCamera()
  cameraType = 118
end
function SetSpikeIdleCamera()
  cameraType = 120
end
local SNDFloorDrop
local WaterPourEmitters = {}
local WaterSplashEmitters = {}
local soundEvents = {
  WaterPourLoop = "SND_MECH_Cal500_SunMoon_WTR_Pour_Flow_02_LP",
  WaterSplashLoop = "SND_MECH_Cal500_SunMoon_WTR_Waterfall_Ground_Sml_LP",
  WaterFillLoop = "SND_MECH_Cal500_SunMoon_WTR_Pour_Flow_01_LP",
  CoversOpen = "SND_MECH_Cal500_SunMoon_Covers_Open",
  FloorDrop01 = "SND_MECH_Cal500_SunMoon_Floor_Drop_01",
  FloorDrop01_LP = "SND_MECH_Cal500_SunMoon_Floor_Drop_LP",
  FloorDrop02 = "SND_MECH_Cal500_SunMoon_Floor_Drop_02",
  FloorDropTimed = "SND_MECH_Cal500_SunMoon_Floor_Drop_Timed",
  WaterLapsLoop = "SND_MECH_Cal500_SunMoon_WTR_Lap_LP",
  FloorDrown = "SND_MECH_Cal500_SunMoon_Drown_Fail"
}
function SoundInit()
  SNDFloorDrop = drop:FindSingleSoundEmitterByName("SNDFloorDrop")
  WaterPourEmitters = GameObjects.WaterStreams.SoundEmitters
  WaterSplashEmitters = GameObjects.WaterSplashes.SoundEmitters
end
function PlayWaterPourSoundToFrame(endFrame)
  for i = 1, #WaterPourEmitters do
    LD.PlayLoopingSoundToAnimFrame(WaterPourEmitters[i], waterPlane, soundEvents.WaterPourLoop, 0, endFrame)
  end
end
function PlayWaterSplashSoundToFrame(endFrame)
  for i = 1, #WaterSplashEmitters do
    LD.PlayLoopingSoundToAnimFrame(WaterSplashEmitters[i], waterPlane, soundEvents.WaterSplashLoop, 0, endFrame)
  end
end
function PlayWaterFillSound(endFrame, startFrame)
  LD.PlayLoopingSoundToAnimFrame(SNDFloorDrop, waterPlane, soundEvents.WaterFillLoop, startFrame or 0, endFrame)
end
function PlaySoundLeverCoversOpen()
  LD.PlaySound(GameObjects.WaterTrap_Levers_02:FindSingleSoundEmitterByName("SNDLeverCoverPlates"), soundEvents.CoversOpen)
end
function PlaySoundFloorDrop01()
  LD.PlaySound(SNDFloorDrop, soundEvents.FloorDrop01)
  PlaySoundFloorWaterLapsLoop()
end
function PlaySoundFloorDrop01_Loop(endFrame)
  LD.PlayLoopingSoundToAnimFrame(SNDFloorDrop, GameObjects.dunkAnim, soundEvents.FloorDrop01_LP, 0, endFrame)
end
function PlaySoundFloorDrop02()
  LD.PlaySound(SNDFloorDrop, soundEvents.FloorDrop02)
end
function PlaySoundFloorDropTimed()
  LD.PlaySound(SNDFloorDrop, soundEvents.FloorDropTimed)
end
function PlaySoundFloorWaterLapsLoop()
  LD.PlaySound(SNDFloorDrop, soundEvents.WaterLapsLoop)
end
function StopSoundFloorWaterLapsLoop()
  LD.StopSound(SNDFloorDrop, soundEvents.WaterLapsLoop)
end
function PlaySoundOnDrown()
  LD.PlaySound(SNDFloorDrop, soundEvents.FloorDrown)
  game.Audio.StartMusic("SND_MX_CAL_vault_puzzle_trap_1_death")
end
function SoundDebugTable()
  local debugTable = {}
  debugTable.Title = "Water Trap Sound Info"
  debugTable.X = 2
  debugTable.Y = 10
  debugTable.TitleColor = engine.Vector.New(255, 0, 128)
  table.insert(debugTable, {
    "WaterPlaneAnim: ",
    waterPlane.AnimFrame
  })
  table.insert(debugTable, {
    "WaterPlaneAnimLength: ",
    waterPlane.AnimLengthFrames
  })
  table.insert(debugTable, {
    "Drop Anim: ",
    drop.AnimFrame
  })
  table.insert(debugTable, {
    "DropAnimLength: ",
    drop.AnimLengthFrames
  })
  table.insert(debugTable, {
    "Ceiling Anim: ",
    GameObjects.spikedRoof.AnimFrame
  })
  table.insert(debugTable, {
    "CeilingAnimLength: ",
    GameObjects.spikedRoof.AnimLengthFrames
  })
  engine.DrawDebugTable(debugTable)
end
