local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local camCollisionCheck = require("camera.collisioncheck")
local uiCalls = require("ui.uicalls")
local TUT = require("game.GlobalTutorials")
local CCOS = require("camera.camera_oneshot")
local breakablePlanks
local rightBifrostCarryActive = false
local leftBifrostCarryActive = false
local runeFanCombined = false
local puzzleComplete = false
local camEnableFinalPullCams = false
local camRuneInPlace = false
local camDoorActivated = false
local solveCrankZone
local camRuneBowlSolveDelay = timers.StartLevelTimer(12)
camRuneBowlSolveDelay:Stop()
local camStatueActivatePart1, camStatueActivatePart2
local canToggleBothActiveCriteria = true
local SNDHammerGlow, SNDDeerBeam, SNDDoorBeam, motion
local paused = true
function OnScriptLoaded(level, obj)
  solveCrankZone = level:GetGameObject("CamSolveCrankZoneGroup")
  solveCrankZone:HideCameraVolume()
  breakablePlanks = level:GetGameObject("BreakablePlanks")
  SNDHammerGlow = GameObjects.SNDGrpHammerGlow:FindSingleSoundEmitterByName("SNDHammerGlow")
  SNDDeerBeam = GameObjects.SNDGrpDeerBeam:FindSingleSoundEmitterByName("SNDDeerBeam")
  SNDDoorBeam = GameObjects.SNDGrpDoorBeam:FindSingleSoundEmitterByName("SNDDoorBeam")
end
function OnFirstStart(level, obj)
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_1a_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_1b_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_2a_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_2b_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_3a_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_3b_peak100_"):Hide()
  LD.HideFX(GameObjects.DeerStatue_Beam_FX)
  GameObjects.CarryBifrostLight_LeftTop.LuaObjectScript.DisableInteract()
  LD.HideFX(GameObjects.runefan_success_peak100)
end
function OnStartGameFromThisLevel(level)
end
function OnPreStart(level)
  if puzzleComplete then
    GameObjects.Tbar_Peak100_.LuaObjectScript.SetLockWhenFullyCranked(true)
  end
end
function OnStart(level, obj)
  SoundOnStart()
  GameObjects.Tbar_Peak100_.LuaObjectScript.RegisterBackwardPullCallback(LineCrankPulledBackwards)
end
function OnUpdate(level, obj)
  ShowSoundDebugTable()
  if leftBifrostCarryActive == true and rightBifrostCarryActive == true and camEnableFinalPullCams == false then
    solveCrankZone:ShowCameraVolume()
    camEnableFinalPullCams = true
  end
  if camRuneBowlSolveDelay.fired == false and camRuneBowlSolveDelay.running == true then
    game.Camera.SubmitCameraByName("PLYR_Crank_Pull_Son_Using_Sand")
  end
  if camStatueActivatePart1 ~= nil then
    camStatueActivatePart1:Update()
  end
  if camStatueActivatePart2 ~= nil then
    camStatueActivatePart2:Update()
  end
end
function Debug_SolveRuneFanPuzzle()
  LD.BreakObject(breakablePlanks)
  GameObjects.CrankRuneFan:JumpAnimToFrame(0)
  GameObjects.CrankRuneFan:FindSingleGOByName("StraightCrankHandle"):FindSingleGOByName("AttachPointFront").LuaObjectScript.Disable()
  GameObjects.CarryBifrostLight_LeftTop:SetWorldPosition(GameObjects.CarryBifrostLight_LeftBase.WorldPosition)
  GameObjects.CarryBifrostLight_LeftTop:SetWorldFacing(GameObjects.CarryBifrostLight_LeftBase:GetWorldForward())
  GameObjects.CarryBifrostLight_LeftTop.LuaObjectScript.SetCrystalObjectStates(2)
  GameObjects.CarryBifrostLight_LeftBase.LuaObjectScript.SetCrystalLit(true)
  GameObjects.CarryBifrostLight_RightTop:SetWorldPosition(GameObjects.CarryBifrostLight_RightBase.WorldPosition)
  GameObjects.CarryBifrostLight_RightTop:SetWorldFacing(GameObjects.CarryBifrostLight_RightBase:GetWorldForward())
  GameObjects.CarryBifrostLight_RightTop.LuaObjectScript.SetCrystalObjectStates(2)
  GameObjects.CarryBifrostLight_RightBase.LuaObjectScript.SetCrystalLit(true)
  GameObjects.deer_statue.Child:JumpAnimToFrame(GameObjects.deer_statue.Child.AnimLengthFrames)
  GameObjects.deerstatue_gloweyes_peak100_1.Child:Show()
  GameObjects.deerstatue_gloweyes_peak100_1.Child:JumpAnimToFrame(GameObjects.deerstatue_gloweyes_peak100_1.Child.AnimLengthFrames)
  GameObjects.deerstatue_gloweyes_peak100_2.Child:Show()
  GameObjects.deerstatue_gloweyes_peak100_2.Child:JumpAnimToFrame(GameObjects.deerstatue_gloweyes_peak100_2.Child.AnimLengthFrames)
  GameObjects.deerstatue_glowhammer_peak100_P.Child:Show()
  GameObjects.deerstatue_glowhammer_peak100_P.Child:JumpAnimToFrame(GameObjects.deerstatue_glowhammer_peak100_P.Child.AnimLengthFrames)
  GameObjects.HingeDoor_MagicDoor.LuaObjectScript.ForceReveal()
end
function CollapseExitZoneRubble()
  GameObjects.re_entry_collaps_break.Child:PlayAnimToEnd()
end
function BreakablePlanksDestroyed()
  GameObjects.BifrostLight_LeftTop_Fall:PlayAnimToEnd()
  GameObjects.Bifrost_Falling_tell_P.Child:HideParticleEmitter()
  turnOffCeilingCreaks()
end
function LeftBifrostCarryON()
  leftBifrostCarryActive = true
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_1a_peak100_"):Show()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_1b_peak100_"):Show()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_2a_peak100_"):Show()
  AudioFanRunesActivate()
  if rightBifrostCarryActive then
    CheckForPuzzleSolved()
    if puzzleComplete == false then
      _G.SCA_WaitForRuneReveal_Enable()
      GameObjects.puzzleRunebowl.LuaObjectScript.CrystalSolvedAndWait()
      GameObjects.SCA_WaitByRuneBowlIdle.LuaObjectScript.Disable()
    end
  end
end
function LeftBifrostCarryOFF()
  leftBifrostCarryActive = false
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_1a_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_1b_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_2a_peak100_"):Hide()
  AudioFanRunesDeactivate()
  MissingElementForSolve()
  _G.SCA_WaitForRuneReveal_Disable()
  if puzzleComplete == false then
    _G.SCA_WaitForRuneReveal_Disable()
    GameObjects.SCA_WaitByRuneBowlIdle.LuaObjectScript.Enable()
  end
end
function RightBifrostCarryON()
  rightBifrostCarryActive = true
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_2b_peak100_"):Show()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_3a_peak100_"):Show()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_3b_peak100_"):Show()
  AudioFanRunesActivate()
  if leftBifrostCarryActive then
    CheckForPuzzleSolved()
    if puzzleComplete == false then
      _G.SCA_WaitForRuneReveal_Enable()
      GameObjects.puzzleRunebowl.LuaObjectScript.CrystalSolvedAndWait()
      GameObjects.SCA_WaitByRuneBowlIdle.LuaObjectScript.Disable()
    end
  end
end
function RightBifrostCarryOFF()
  rightBifrostCarryActive = false
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_2b_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_3a_peak100_"):Hide()
  GameObjects.CrankRuneFan:FindSingleGOByName("runefan_3b_peak100_"):Hide()
  AudioFanRunesDeactivate()
  MissingElementForSolve()
  _G.SCA_WaitForRuneReveal_Disable()
  if puzzleComplete == false then
    _G.SCA_WaitForRuneReveal_Disable()
    GameObjects.SCA_WaitByRuneBowlIdle.LuaObjectScript.Enable()
  end
end
function DiscoverRuneStart()
  GameObjects.BtrTimer_RuneBowlHint01.LuaObjectScript.Cancel()
end
function CheckForPuzzleSolved()
  if runeFanCombined and rightBifrostCarryActive and leftBifrostCarryActive then
    GameObjects.Tbar_Peak100_.LuaObjectScript.DisablePlayerInput()
    LD.ShowFX(GameObjects.runefan_success_peak100)
    AudioFanRunesActivate()
    if GameObjects.puzzleRunebowl.LuaObjectScript.IsRuneDiscovered() == false then
      GameObjects.sandBowlAnswer.LuaObjectScript.Enable()
    end
  end
end
function PuzzleSolved()
  if puzzleComplete then
    return
  end
  EnableRuneBowl()
  StopAudioLoops()
end
function DetachFromCrank()
  GameObjects.Tbar_Peak100_.LuaObjectScript.EnablePlayerInput()
  GameObjects.Tbar_Peak100_.LuaObjectScript.RemovePlayerImmediate()
  GameObjects.Tbar_Peak100_.LuaObjectScript.EnablePlayerInput()
end
function LineCrankPulledBackwards(newCycle)
  if newCycle == 0 then
    runeFanCombined = true
    if rightBifrostCarryActive and leftBifrostCarryActive then
      GameObjects.Tbar_Peak100_.LuaObjectScript.DisablePlayerInput()
    end
  end
end
function RuneFanNotCombined()
  if GameObjects.Tbar_Peak100_.LuaObjectScript.GetCurrentCycle() >= 3 and not GameObjects.Tbar_Peak100_.LuaObjectScript.PlayerIsAttached() then
    StopAudioLoops()
  end
  runeFanCombined = false
  MissingElementForSolve()
end
function DisablePromptWhileRewinding()
  GameObjects.Tbar_Peak100_.LuaObjectScript.Disable()
end
function CrankAtEnd()
  if rightBifrostCarryActive and leftBifrostCarryActive and runeFanCombined then
    CheckForPuzzleSolved()
  end
  paused = true
end
function CrankAtBeginning()
  GameObjects.Tbar_Peak100_.LuaObjectScript.Enable()
  if not GameObjects.Tbar_Peak100_.LuaObjectScript.PlayerIsAttached() then
    StopAudioLoops()
  end
  paused = true
end
function MissingElementForSolve()
  DisableSandBowlAnswer()
  LD.HideFX(GameObjects.runefan_success_peak100)
end
function EnableRuneBowl()
  GameObjects.NavObstacle_FanPuzzle:HideNavObstacle()
end
function DisableSandBowlAnswer()
  GameObjects.sandBowlAnswer.LuaObjectScript.Disable()
  GameObjects.NavObstacle_FanPuzzle:ShowNavObstacle()
end
function SonApproachingRuneBowl()
  GameObjects.NavObstacle_FanPuzzle:HideNavObstacle()
end
function QuestionComplete()
  if GameObjects.puzzleRunebowl.LuaObjectScript.IsRuneDiscovered() == false then
    GameObjects.puzzleRunebowl.LuaObjectScript.Disable()
  end
end
function DestroyCamera_Part1()
  camStatueActivatePart1 = nil
end
function StartDesignerCam_Part1()
  local fSubmitTime = 7
  camStatueActivatePart1 = CCOS.OneShotCamera.New("PLYR_Crank_Pull_Statue_Start", fSubmitTime)
  camStatueActivatePart1:SetCallback(DestroyCamera_Part1)
  camStatueActivatePart1:Start()
end
function DestroyCamera_Part2()
  camStatueActivatePart2 = nil
end
function StartDesignerCam_Part2()
  local fSubmitTime = 9.6
  camStatueActivatePart1 = CCOS.OneShotCamera.New("PLYR_Vista_Peak100_Door_Solve", fSubmitTime)
  camStatueActivatePart1:SetCallback(DestroyCamera_Part2)
  camStatueActivatePart1:Start()
end
function CameraRuneBowlSolve()
  camRuneBowlSolveDelay:Start()
end
function SetSlowWalk()
  GameObjects.SpeedControl_PuzzleSolved:ShowEntityVolume()
end
function ClearSlowWalk()
  GameObjects.SpeedControl_PuzzleSolved:HideEntityVolume()
end
function EnableCollisionBlockers()
  GameObjects.PathBlockers_DeerScene:ShowCollision()
end
function DisableCollisionBlockers()
  GameObjects.PathBlockers_DeerScene:HideCollision()
end
function SonRuneBowlActivate()
  GameObjects.LeadTheWay_100Hall.LuaObjectScript.Disable()
  GameObjects.LeadTheWay_100Enter.LuaObjectScript.Disable()
  timers.StartLevelTimer(0, StartDesignerCam_Part1)
  timers.StartLevelTimer(6.9, StartDesignerCam_Part2)
  solveCrankZone:HideCameraVolume()
  EnableCollisionBlockers()
  GameObjects.deer_statue.Child:PlayAnimToEnd()
  AudioActivateStatue()
  game.Audio.StartMusic("SND_MX_PEAK_statue_secret_door")
  GameObjects.Tbar_Peak100_.LuaObjectScript.CrankComplete()
  GameObjects.Tbar_Peak100_.LuaObjectScript.RemovePlayerImmediate()
  GameObjects.Tbar_Peak100_.LuaObjectScript.EnablePlayerInput()
  SetSlowWalk()
  LD.CallFunctionAfterDelay(_G.SCA_MagicDoor_Enable, 11)
  timers.StartLevelTimer(12, function()
    GameObjects.LeadTheWay_100Hall.LuaObjectScript.Enable()
    GameObjects.LeadTheWay_100Enter.LuaObjectScript.Enable()
  end)
  LD.CallFunctionAfterDelay(function()
    LD.ShowFX(GameObjects.DeerStatue_Beam_FX, {cycle = true})
    AudioDeerBeam()
  end, 7)
  LD.CallFunctionAfterDelay(function()
    CleanupSuccessFXAndEnableDoor()
    StopAudioDeerBeam()
  end, 15.3)
  LD.CallFunctionAfterDelay(ClearSlowWalk, 16.5)
  LD.CallFunctionAfterDelay(DisableCollisionBlockers, 16.5)
  LD.CallFunctionAfterDelay(function()
    AudioDoorBeamImpact()
  end, 7.3)
  LD.CallFunctionAfterDelay(function()
    GameObjects.HingeDoor_MagicDoor.LuaObjectScript.RevealDoor()
    AudioDoorBeam()
  end, 8)
  GameObjects.deerstatue_gloweyes_peak100_1.Child:Show()
  GameObjects.deerstatue_gloweyes_peak100_1.Child:JumpAnimToFrame(0)
  GameObjects.deerstatue_gloweyes_peak100_1.Child:PlayAnimToEnd()
  GameObjects.deerstatue_gloweyes_peak100_2.Child:Show()
  GameObjects.deerstatue_gloweyes_peak100_2.Child:JumpAnimToFrame(0)
  GameObjects.deerstatue_gloweyes_peak100_2.Child:PlayAnimToEnd()
  GameObjects.deerstatue_glowhammer_peak100_P.Child:Show()
  GameObjects.deerstatue_glowhammer_peak100_P.Child:JumpAnimToFrame(0)
  GameObjects.deerstatue_glowhammer_peak100_P.Child:PlayAnimToEnd()
  AudioHammerGlow()
  puzzleComplete = true
  GameObjects.Zone_ContextIdle_LookAround:HideEntityVolume()
  game.AI.FindSon():CallScript("ClearBehaviorContext")
  GameObjects.SCA_WaitByRuneBowlIdle.LuaObjectScript.Disable()
  _G.SCA_WaitForRuneReveal_Disable()
  GameObjects.SCA_SandBowlSolveReact.LuaObjectScript.Enable()
  timers.StartLevelTimer(3, function()
    GameObjects.Reaction_DeerPuzzleSolve.LuaObjectScript.Trigger()
    game.AI.FindSon():SetMaxSpeedOverride(0)
  end)
end
function CleanupSuccessFXAndEnableDoor()
  LD.HideFX(GameObjects.DeerStatue_Beam_FX)
  LD.HideFX(GameObjects.deerstatue_gloweyes_peak100_1)
  LD.HideFX(GameObjects.deerstatue_gloweyes_peak100_2)
  LD.HideFX(GameObjects.deerstatue_glowhammer_peak100_P)
  GameObjects.SCA_SandBowlSolveReact.LuaObjectScript.Disable()
  GameObjects.HingeDoor_MagicDoor.LuaObjectScript.Enable()
end
function CancelMsg()
  uiCalls.UI_Event_TurnOffDesignerMessage()
end
function IntroTextMessage()
  TUT.AscendTheCave_Tutorial()
end
function CamActivateDoorSolve()
  game.Camera.SubmitCameraByName("PLYR_Vista_Peak100_Door_Solve")
end
local fanEmitter, crankEmitter, SNDWoodCreaksBreakable
local soundCrankOverrides = {
  OnReturnToStart = "SND_MECH_Peak100_Crank_Push_Latch",
  OnReturnToStartFrame = -1,
  OnForward = "",
  OnForwardFrame = -1,
  OnBackward = "",
  OnBackwardFrame = -1,
  OnFastForward = "SND_MECH_Peak100_Crank_Rewind_Start",
  OnFastForwardFrame = -1,
  OnRewind = "",
  OnRewindFrame = -1,
  OnEnd = "SND_MECH_Peak100_Crank_Pull_Latch",
  OnEndFrame = -1
}
local soundDrivenObjectOverrides = {
  OnReturnToStart = "SND_MECH_Peak100_Fan_Push_Latch",
  OnReturnToStartFrame = -1,
  OnForward = "",
  OnForwardFrame = -1,
  OnBackward = "",
  OnBackwardFrame = -1,
  OnFastForward = "SND_MECH_Peak100_Fan_Move_Start",
  OnFastForwardFrame = -1,
  OnRewind = "",
  OnRewindFrame = -1,
  OnEnd = "SND_MECH_Peak100_Fan_Pull_Latch",
  OnEndFrame = -1,
  OnStuckAtEnd = "SND_MECH_Peak100_Fan_Pull_Stuck",
  OnStuckAtEndFrame = -1,
  OnStuckAtStart = "SND_MECH_Peak100_Fan_Pull_Stuck",
  OnStuckAtStartFrame = -1
}
function SoundOnStart()
  GameObjects.Tbar_Peak100_.LuaObjectScript.CrankSoundSetup(soundCrankOverrides)
  GameObjects.Tbar_Peak100_.LuaObjectScript.DrivenObjectSoundSetup(soundDrivenObjectOverrides)
  fanEmitter = GameObjects.CrankRuneFan:FindSingleSoundEmitterByName("SNDCrankRuneFan")
  crankEmitter = GameObjects.Tbar_Peak100_.Child:FindSingleSoundEmitterByName("SNDBasicCrankObject")
  SNDWoodCreaksBreakable = GameObjects.SNDGrpWoodCreaksBreakable:FindSingleSoundEmitterByName("SNDWoodCreaksBreakable")
end
function AudioFanRunesActivate()
  LD.PlaySound(fanEmitter, "SND_MECH_Plate_Puzzle_Solve_Lights_On")
end
function AudioFanRunesDeactivate()
  LD.PlaySound(fanEmitter, "SND_MECH_Plate_Puzzle_Solve_Lights_Off")
end
function AudioActivateStatue()
  LD.PlaySoundOnFrame(SNDHammerGlow, GameObjects.deer_statue.Child, "SND_CINE_Peak100_Statue_Activate", 44, "forward")
end
function AudioHammerGlow()
  LD.PlaySound(SNDHammerGlow, "SND_MAG_Peak100_Hammer_Glow")
end
function AudioDeerBeam()
  LD.PlaySound(SNDDeerBeam, "SND_MAG_Peak100_Beam_Launch")
  LD.PlaySound(SNDDeerBeam, "SND_MAG_Peak100_Beam_LP")
end
function AudioDoorBeamImpact()
  LD.PlaySound(SNDDoorBeam, "SND_MECH_Plate_Puzzle_Solve_Light_Hits_Emblem")
end
function AudioDoorBeam()
  LD.PlaySound(SNDDoorBeam, "SND_MAG_Peak100_Beam_Impact")
end
function StopAudioDeerBeam()
  LD.StopSound(SNDDeerBeam, "SND_MAG_Peak100_Beam_LP")
end
function PlayAudioLoops()
  LD.PlaySound(fanEmitter, "SND_MECH_Peak100_Fan_Push_LP")
  LD.PlaySound(crankEmitter, "SND_MECH_Peak100_Crank_Pull_LP")
end
function StopAudioLoops()
  LD.StopSound(fanEmitter, "SND_MECH_Peak100_Fan_Push_LP")
  LD.StopSound(crankEmitter, "SND_MECH_Peak100_Crank_Pull_LP")
  paused = true
end
function PlayStopSound()
  local currentCycle = GameObjects.Tbar_Peak100_.LuaObjectScript.GetCurrentCycle()
  if motion == "forward" and currentCycle < 3 then
    LD.PlaySound(fanEmitter, "SND_MECH_Peak100_Fan_Move_Stop")
    LD.PlaySound(crankEmitter, "SND_MECH_Peak100_Crank_Push_Stop")
  elseif motion == "backward" and 0 < currentCycle then
    LD.PlaySound(fanEmitter, "SND_MECH_Peak100_Fan_Move_Stop")
    LD.PlaySound(crankEmitter, "SND_MECH_Peak100_Crank_Pull_Stop")
  elseif motion == "rewind" then
    LD.PlaySound(fanEmitter, "SND_MECH_Peak100_Fan_Rewind_Latch")
    LD.PlaySound(crankEmitter, "SND_MECH_Peak100_Crank_Rewind_Latch")
  end
  paused = true
end
function FanForward()
  motion = "forward"
  if paused then
    paused = false
    LD.PlaySound(fanEmitter, "SND_MECH_Peak100_Fan_Move_Start")
    LD.PlaySound(crankEmitter, "SND_MECH_Peak100_Crank_Push_Start")
  end
end
function FanBackward()
  motion = "backward"
  if paused then
    paused = false
    LD.PlaySound(fanEmitter, "SND_MECH_Peak100_Fan_Move_Start")
    LD.PlaySound(crankEmitter, "SND_MECH_Peak100_Crank_Pull_Start")
  end
end
function FanRewind()
  motion = "rewind"
end
function turnOffCeilingCreaks()
  LD.StopSound(SNDWoodCreaksBreakable, "SND_AMB_EMIT_Wooden_Beam_Creak_LP")
end
function ShowSoundDebugTable()
end
function OnSaveCheckpoint(level, obj)
  return {puzzleComplete = puzzleComplete}
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  puzzleComplete = savedInfo.puzzleComplete
end
