local LD = require("design.LevelDesignLibrary")
local timer = require("level.timer")
local checkpoint = require("level.checkpoint")
local player, son, thisLevel, pad
local camShakeLarge = {
  EffectName = "FSE_shake_temp_Generic_Large",
  Duration = 1
}
local gearCrank, cart, cartBody
local lastCartDir = "idle"
local TL_CartExitTop, TL_CartExitBottom, backExit_Collision
local isRopeBreakableBroken = false
local isCartRopeDropped = false
local isSecondRopeDropped = false
local cartPinned = false
local cartZone, ledgeZone
local cartPos = ""
local readyForCart = false
local doorWad
local bBiFrostCrystalDropped = false
local cartGear, BanterScript_Stn800, recallButtonMonitor, bMantleClose
function OnScriptLoaded(level)
  player = game.Player:FindPlayer()
  pad = player.Pad
  son = game.AI.FindSon()
  thisLevel = level
  gearCrank = GameObjects.WheelCrank
  cart = GameObjects.SonCart_CrankSetup
  cartBody = GameObjects.masonSkyCartBody00.Child
  cartGear = GameObjects.masonSkyCartPully00_P:FindSingleGOByName("WallGears_Single")
  backExit_Collision = GameObjects.BackDoor_Collision
  TL_CartExitTop = GameObjects.TraverseLink_OutOfCart
  TL_CartExitBottom = GameObjects.TraverseLink_JumpOutofCart
  cartZone = GameObjects.cartZone
  ledgeZone = GameObjects.ledgeZone
  BanterScript_Stn800 = GameObjects.Btr_Stn800
  local monitors = require("level.MonitorLibrary")
  recallButtonMonitor = monitors.CreateTriangleButtonMonitor()
  recallButtonMonitor:OnButtonDown(DisableCartMantle)
end
function OnFirstStart(level)
  LD.SetEntityVariable("STN_ReturnToWad150", true)
  backExit_Collision:HideCollision()
  GameObjects.RopeBreakable_Linger:Hide()
  GameObjects.TraverseLink_JumpOutofCart:HideTraverseLink()
  TL_CartExitTop:HideTraverseLink()
  TL_CartExitBottom:HideTraverseLink()
end
function OnStart(level)
  if game.Level.GetVariable("CompletedCineNumber") == 360 then
    son:CallScript("EnterBehaviorContext", "SICK_BEHAVIOR_CONTEXT_CONFIG")
  end
  doorWad = game.FindLevel("Stn210_LoadingDoors")
  GameObjects.masonSkyCartPully00_P.Child:StartAnim("envSkyCartPulleyTraverse")
  game.GameObject.AnimSync(GameObjects.masonSkyCartPully00_P.Child, GameObjects.SonCart_CrankSetup, 1)
  SoundOnStart()
end
function OnWadLoaded(level, newLevel)
  if newLevel.Name == "WAD_Stn210_LoadingDoors" then
    doorWad = newLevel
    if not son:IsAvailableForCombat() and not son:IsAvailableForSync() then
      doorWad:CallScript("LockDoor_ChiselDoor")
    end
  end
end
function OnUpdate(level)
  if game.World.IsInsideCameraZone(player.WorldPosition, "ZoneCamShortcutRoomDoor") and player:HasMarker("Opening") and player:HasMarker("Door") then
    game.Camera.SubmitCameraByName("PLYR_Vista_Stn800_DoorOpen")
  end
end
function OnSaveCheckpoint(level)
  return {
    isRopeBreakableBroken = isRopeBreakableBroken,
    isCartRopeDropped = isCartRopeDropped,
    isSecondRopeDropped = isSecondRopeDropped,
    cartPinned = cartPinned,
    levelState = checkpoint.Save()
  }
end
function OnRestoreCheckpoint(level, savedInfo)
  isRopeBreakableBroken = savedInfo.isRopeBreakableBroken
  isCartRopeDropped = savedInfo.isCartRopeDropped
  isSecondRopeDropped = savedInfo.isSecondRopeDropped
  cartPinned = savedInfo.cartPinned
  checkpoint.Restore(savedInfo.levelState)
end
function LoadCheck_Stn800_Mult()
  game.UI.LoadCheck("Stn130_RightHand", "Stn210_LoadingDoors", "WaterGlobal")
end
function LoadCheck_Stn800_SnowGlobal()
  game.UI.LoadCheck("SnowGlobal")
end
function Disable150FXVolumes()
  local stn075 = game.FindLevel("Stn075_Lighting")
  if stn075 ~= nil then
    stn075:CallScript("TurnOffFX150")
  end
end
function Enable_LTW_Stn800()
  GameObjects.LTW_Stn800_EntryHall.LuaObjectScript.Enable()
end
function Disable_LTW_Stn800()
  GameObjects.LTW_Stn800_EntryHall.LuaObjectScript.Disable()
end
function Disable_CA_Stn800_Clue()
  bBiFrostCrystalDropped = true
  GameObjects.CA_PointUp_Stn800_LookAtBifrost.LuaObjectScript.Disable()
  GameObjects.CA_Observe_Forward_BifrostTurret.LuaObjectScript.Enable()
  GameObjects.CA_Observe_Forward_VibrateChestTurret.LuaObjectScript.Enable()
end
function On_CA_Stn800_Clue()
  if bBiFrostCrystalDropped == false then
    GameObjects.CA_PointUp_Stn800_LookAtBifrost.LuaObjectScript.Enable()
  end
end
function Off_CA_Stn800_Clue()
  if bBiFrostCrystalDropped == false then
    GameObjects.CA_PointUp_Stn800_LookAtBifrost.LuaObjectScript.Disable()
  end
end
function BTR_PlayFoundBoost()
  BanterScript_Stn800.LuaObjectScript.PlayFoundBoost()
end
function ReadyForCart()
  MakeSonUnavailable()
  GameObjects.EZ_ToggleDockEndSit:HideEntityVolume()
  if cartPos == "Bottom" then
    EnterCart()
  else
    GameObjects.CA_WaitForCart.LuaObjectScript.Enable()
    readyForCart = true
  end
end
function BRT_PlayPathOther()
  BanterScript_Stn800.LuaObjectScript.PlayPathOther()
end
function EnterCart()
  LockCrank(true)
  engine.SendHook("OnStandGround", son, true)
  GameObjects.CA_RideCart.LuaObjectScript.Enable()
  GameObjects.CA_TopIdle.LuaObjectScript.Disable()
  GameObjects.CA_RopeWait1.LuaObjectScript.Disable()
  if cartGear.LuaObjectScript.IsAxePinned() == true and cartPos == "Top" then
    pad:DisableGameButton(tweaks.ePad.kPadTriangle)
  end
  if readyForCart == true then
    GameObjects.CA_WaitForCart.LuaObjectScript.Disable()
    readyForCart = false
  end
end
function MantleNear()
  bMantleClose = true
end
function MantleAway()
  bMantleClose = false
end
function DisableCartMantle()
  if bMantleClose == true then
    TL_CartExitTop:HideTraverseLink()
  end
end
function BlockAxeRecall()
  pad:DisableGameButton(tweaks.ePad.kPadTriangle)
  timer.StartLevelTimer(1.5, function()
    pad:EnableGameButton(tweaks.ePad.kPadTriangle)
  end)
end
function EnteredCart()
  UnlockCrank()
  if cartGear.LuaObjectScript.IsAxePinned() == true then
    pad:EnableGameButton(tweaks.ePad.kPadTriangle)
  end
end
function ExitCartTop()
  LockCrank(true)
  if isCartRopeDropped == true then
    GameObjects.CA_TopIdle.LuaObjectScript.Enable()
  else
    GameObjects.CA_RopeWait1.LuaObjectScript.Enable()
  end
  GameObjects.CA_RideCart.LuaObjectScript.Disable()
end
function ExitedCart()
  engine.SendHook("OnStandGround", son, false)
  UnlockCrank()
end
function RopeReady()
  if not isCartRopeDropped then
    GameObjects.RopeDrop1.LuaObjectScript.EnableSonInteract()
    BTR_PlayFoundRope()
  end
end
function BTR_PlayFoundRope()
  BanterScript_Stn800.LuaObjectScript.PlayFoundRope()
end
function Rope1Released()
  isCartRopeDropped = true
  if cartPos ~= "Top" then
    GameObjects.CA_TopIdle.LuaObjectScript.Enable()
  else
    EnterCart()
  end
end
function Rope2Released()
  isSecondRopeDropped = true
end
function TriggerCartExit(markerGameObject, markerId)
  if cartPos == "Bottom" and markerGameObject == player and son:InsideZone(cartZone) then
    MakeSonAvailable()
    GameObjects.CA_RideCart.LuaObjectScript.Disable()
  end
end
function HideRopeDropColl_Stn800()
  GameObjects.Coll_ChainDrop_Stn800:Hide()
end
function BTR_PlayOhNo()
  if isCartRopeDropped and cartPos == "Top" and cartGear.LuaObjectScript.IsAxePinned() == false then
    BanterScript_Stn800.LuaObjectScript.PlayOhNo()
  end
end
function BTR_PlayThatDidIt()
  if isCartRopeDropped and cartPos == "Top" and cartGear.LuaObjectScript.IsAxePinned() == true then
    BanterScript_Stn800.LuaObjectScript.PlayThatDidIt()
  end
end
function MakeSonUnavailable()
  local availabilityState = {
    AvailableForSync = false,
    AvailableForBanter = true,
    AvailableInLevel = true,
    AvailableForCombat = false
  }
  son:SetNewAvailabilityRequest("LevelDesignScript", availabilityState)
  GameObjects.SpreadDoor_StoneMason.LuaObjectScript.Lock()
  if doorWad ~= nil then
    doorWad:CallScript("LockDoor_ChiselDoor")
  end
end
function MakeSonAvailable()
  son:RemoveAvailabilityRequest("LevelDesignScript")
  GameObjects.SpreadDoor_StoneMason.LuaObjectScript.Unlock()
  if doorWad ~= nil then
    doorWad:CallScript("UnlockDoor_ChiselDoor")
  end
end
function PlayerTopside()
  if cartPos == "Top" then
    if son:InsideZone(cartZone) == true then
      if not son:IsAvailableForCombat() and not son:IsAvailableForSync() then
        MakeSonAvailable()
      end
    else
      EnterCart()
    end
  end
end
function CartAtTop()
  cartPos = "Top"
  TL_CartExitTop:ShowTraverseLink()
  if not isCartRopeDropped and son:InsideZone(cartZone) then
    ExitCartTop()
  elseif isCartRopeDropped and son:InsideZone(ledgeZone) then
    EnterCart()
  end
end
function CartAtMiddle()
  if cartPos == "Middle" then
    return
  end
  cartPos = "Middle"
  TL_CartExitTop:HideTraverseLink()
  TL_CartExitBottom:HideTraverseLink()
  backExit_Collision:ShowCollision()
  if son:InsideZone(cartZone) ~= player:InsideZone(cartZone) then
    MakeSonUnavailable()
  end
end
function CartAtBottom()
  cartPos = "Bottom"
  TL_CartExitBottom:ShowTraverseLink()
  backExit_Collision:HideCollision()
  gearCrank.LuaObjectScript.StopAllLoopingSounds()
  if readyForCart == true then
    EnterCart()
  elseif player:InsideZone(GameObjects.cartExitZone) then
    MakeSonAvailable()
    GameObjects.CA_RideCart.LuaObjectScript.Disable()
  end
end
function FreeCart()
  isRopeBreakableBroken = true
  UnlockCrank()
  GameObjects.HookLatch:PlayAnimToEnd()
  PlayHookBreakSound()
  timer.StartLevelTimer(2.5, AnimateBreakble)
end
function AnimateBreakble()
  GameObjects.RopeBreakable:Hide()
  GameObjects.RopeBreakable_Linger:Show()
  GameObjects.RopeBreakable_Linger:PlayAnimCycle(0.9)
end
function PinCart()
  if cartPos ~= "Bottom" and gearCrank.LuaObjectScript.GetNearestBackwardStopFrame() == 0 then
    CartAtBottom()
  end
  cartPinned = true
  ShakeRumble()
  LockCrank()
end
function UnpinCart()
  cartPinned = false
  if isRopeBreakableBroken == true then
    ShakeRumble()
    UnlockCrank()
  end
end
function LockCrank(lockPlayer)
  gearCrank.LuaObjectScript.Lock()
  if lockPlayer and player:GetCurrentInteractObject() == gearCrank.Child then
    pad:DisableGameButton(tweaks.ePad.kPadCircle)
  end
end
function UnlockCrank()
  if cartPinned == false then
    gearCrank.LuaObjectScript.Unlock()
  end
  pad:EnableGameButton(tweaks.ePad.kPadCircle)
end
function BTR_PlayItsMoving()
  BanterScript_Stn800.LuaObjectScript.PlayItsMoving()
end
function ShakeRumble()
  game.FX.SubmitEffect(camShakeLarge)
end
function PlayAnim_CartUpImpact()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartUpImpact",
    Tween = 0.3
  })
  gearCrank.LuaObjectScript.StopAllLoopingSounds()
  ShakeRumble()
end
function PlayAnim_CartUpStart()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartUpStart",
    Tween = 0.3
  })
  cartBody:OnAnimDone(thisLevel, "PlayAnim_CartUpLean")
  lastCartDir = "forward"
end
function PlayAnim_CartUpLean()
  cartBody:StartAnimation({
    Animation = "envSkyCartUpLean",
    Tween = 0.3
  })
  cartBody:PlayAnimCycle()
end
function PlayAnim_CartUpStop()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartUpStop",
    Tween = 0.3
  })
  cartBody:OnAnimDone(thisLevel, "PlayAnim_CartIdle")
  lastCartDir = "idle"
end
function PlayAnim_CartDownImpact()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartDownImpact",
    Tween = 0.3
  })
  ShakeRumble()
end
function PlayAnim_CartDownStart()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartDownStart",
    Tween = 0.3
  })
  cartBody:OnAnimDone(thisLevel, "PlayAnim_CartDownLean")
  lastCartDir = "backward"
end
function PlayAnim_CartDownLean()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartDownLean",
    Tween = 0.3
  })
  cartBody:PlayAnimCycle()
end
function PlayAnim_CartDownStop()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartDownStop",
    Tween = 0.3
  })
  cartBody:OnAnimDone(thisLevel, "PlayAnim_CartIdle")
  lastCartDir = "idle"
end
function PlayAnim_CartIdle()
  cartBody:ClearAllAnimCallbacks()
  cartBody:StartAnimation({
    Animation = "envSkyCartIdle",
    Tween = 0.3
  })
  cartBody:PlayAnimCycle(0.75)
  lastCartDir = "idle"
end
function UpdateAnimState_PauseEvent()
  local previousCartDir = lastCartDir
  lastCartDir = "idle"
  PlayAnim_GetNextDecisionFromState(previousCartDir, lastCartDir)
end
function UpdateAnimState_ForwardEvent()
  local previousCartDir = lastCartDir
  lastCartDir = "forward"
  PlayAnim_GetNextDecisionFromState(previousCartDir, lastCartDir)
end
function UpdateAnimState_BackwardEvent()
  local previousCartDir = lastCartDir
  lastCartDir = "backward"
  PlayAnim_GetNextDecisionFromState(previousCartDir, lastCartDir)
end
function PlayAnim_GetNextDecisionFromState(oldState, newState)
  if newState == "idle" then
    local currCycle = GameObjects.WheelCrank.LuaObjectScript.GetCurrentCycle()
    if currCycle ~= GameObjects.WheelCrank.LuaObjectScript.GetMaxStopCycle() and currCycle ~= GameObjects.WheelCrank.LuaObjectScript.GetMinStopCycle() then
      if oldState == "forward" then
        PlayAnim_CartUpStop()
      elseif oldState == "backward" then
        PlayAnim_CartDownStop()
      end
    end
  elseif newState == "forward" then
    if oldState == "idle" or oldState == "backward" then
      PlayAnim_CartUpStart()
    end
  elseif newState == "backward" and (oldState == "idle" or oldState == "forward") then
    PlayAnim_CartDownStart()
  end
end
local hookEmitter
local cartSoundOverrides = {
  SoundEmitter = nil,
  UseExplicitSoundMotion = true,
  OnReturnToStart = "SND_MECH_Gondola_StoneMason_Stop_Bang",
  OnForward = "SND_MECH_Gondola_StoneMason_Moving_Down_LP",
  OnBackward = "SND_MECH_Gondola_StoneMason_Moving_Up_LP",
  OnRewind = "SND_MECH_Gondola_StoneMason_Moving_Down_LP",
  OnEnd = "SND_MECH_Gondola_StoneMason_Stop_Bang"
}
function SoundOnStart()
  cartSoundOverrides.SoundEmitter = cart:FindSingleSoundEmitterByName("SNDSonCart")
  GameObjects.WheelCrank.LuaObjectScript.DrivenObjectSoundSetup(cartSoundOverrides)
  hookEmitter = GameObjects.RopeBreakable:FindSingleGOByName("sHook_breakable").Child:FindSingleSoundEmitterByName("SNDSHook")
  LD.PlaySoundAfterDelay(cartSoundOverrides.SoundEmitter, "SND_MECH_Gondola_StoneMason_Idle_LP", 0.5)
end
function PlayHookBreakSound()
  LD.PlaySound(hookEmitter, "SND_MECH_Gondola_StoneMason_Chainlink_Break")
end
