local LD = require("design.LevelDesignLibrary")
local actor = require("narrative.actor")
local CCOS = require("camera.camera_oneshot")
local timers = require("level.timer")
local CCEC = require("camera.camera_cineentercamera")
local thisObj, thisLevel, player, bridgeObj, thorStatue, kraActor, sonActor
local synchJointStr = "SerpentTranslate_SynchJoint"
local mSStartJointStr = "MS_StartJoint"
local serpentTranslateBranchStr = "BRA_SerpentTranslate"
local cal100, cal200, camOneShot_Snake_015, camOneShot_Snake_020, camOneShot_Snake_030, camOneShot_Snake_040, cineEnterSerpentTranslate
local waterdropPOIEnded = false
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  thorStatue = GameObjects.thor_statue_break
  game.SubObject.SetForgetOnCheckpoint(obj)
  game.SubObject.Sleep(obj)
end
function OnStart(level, obj)
  if game.Level.GetVariable("CompletedCineNumber") < 340 then
    SetupActors()
  end
  GameObjects.CA_snakeLeaving.LuaObjectScript.Disable()
  GameObjects.CA_waterLevelDropping.LuaObjectScript.Disable()
end
function OnUpdate(level, obj)
  if cineEnterSerpentTranslate ~= nil then
    cineEnterSerpentTranslate:Update()
  end
  if camOneShot_Snake_015 ~= nil then
    camOneShot_Snake_015:Update()
  end
  if camOneShot_Snake_020 ~= nil then
    camOneShot_Snake_020:Update()
  end
  if camOneShot_Snake_030 ~= nil then
    camOneShot_Snake_030:Update()
  end
  if camOneShot_Snake_040 ~= nil then
    camOneShot_Snake_040:Update()
  end
end
function SetupActors()
  local GetPlayer = function()
    return player
  end
  kraActor = actor.Actor.New("SERPENT TRANSLATE: Kratos Actor", GetPlayer)
  sonActor = actor.Actor.New("SERPENT TRANSLATE: Son Actor", game.AI.FindSon)
end
function SetupCineSequence()
  local ND = require("design.NarrativeDesignLibrary")
  local KraWalkSpeed = ND.KraWalkSpeed
  local StopTurnRadius = ND.StopTurnRadius
  ND = nil
  local cineSeq = LD.CreateCineSequence(thisLevel, thisObj, "Serpent Translate Sequence")
  local slaveTab = {
    {Actor = sonActor}
  }
  cineSeq:SetPostSkipMusic("SND_MX_CAL_start_master")
  cineSeq:MarkAbleToSkip()
  cineSeq:Do(function()
    game.SubObject.Wake(thisObj)
  end)
  cineSeq:Do(function()
    cineEnterSerpentTranslate = CCEC.CineEnterCamera.New("ENV_CineEnter_narCalSerpentTranslate000CineScene", 7.3, nil)
    cineEnterSerpentTranslate:Start()
  end)
  cineSeq:RequestCineModeAndWait(kraActor, thisObj)
  cineSeq:WaitForLoadCheck("Cal215_SnakeHornCine1")
  cineSeq:Do(SetupSnake)
  cineSeq:ActorForceApproachAndWait(kraActor, {
    Branch = serpentTranslateBranchStr,
    ReferenceJoint = synchJointStr,
    speed = KraWalkSpeed,
    stop = false,
    radius = StopTurnRadius,
    strafe_distance = 1,
    weapon_state = "bare"
  })
  cineSeq:ActorSync(kraActor, {
    Slaves = slaveTab,
    Branch = serpentTranslateBranchStr,
    ReferenceJoint = synchJointStr
  })
  cineSeq:Do(AnimateSnake)
  cineSeq:Do(ThorStatueBreak)
  cineSeq:Do(GetCal100())
  cineSeq:Do(function()
    timers.StartLevelTimer(8, function()
      cal100:CallScript("ShowSnakePushCameraZone")
    end)
  end)
  cineSeq:WaitForFunctionTrue(function()
    return player.AnimPercent >= 0.02
  end)
  cineSeq:Do(ShowSnakeAndHideIdleMesh)
  cineSeq:WaitUntilActorAnimPastPercentage(kraActor, 0.96)
  cineSeq:Do(RecenterCameraOnBridgePushStart)
  cineSeq:WaitForAndCompleteCineMode(kraActor, thisObj)
  cineSeq:Do(game.Cinematics.EnableCinematicMode)
  cineSeq:StartPOIMoment(2.5)
  cineSeq:StopPuppetingActor(kraActor)
  cineSeq:StopPuppetingActor(sonActor)
  cineSeq:Do(function()
    if cineSeq.skipping then
      player:Warp(engine.Vector.New(23.1, -20.6, 2.8), -player:GetWorldForward())
      game.AI.FindSon():Warp(engine.Vector.New(24.1, -20.6, 2.8), game.AI.FindSon():GetWorldForward())
    else
      cineSeq.ableToSkip = false
      game.SetAbleToSkip(false)
    end
  end)
  cineSeq:Do(function()
    cineSeq:SetMaxSkipSpeedup(5)
  end)
  cineSeq:Do(function()
    LD.Trigger_WaterDrop02()
  end)
  cineSeq:SetCompletedCineNumber(340)
  cineSeq:Do(ReplaceBrokenThorStatue)
  cineSeq:Do(DisableElevatorAndHorn)
  cineSeq:Do(function()
    game.Audio.PlayBanter("030_SpecialChisel")
  end)
  cineSeq:WaitSeconds(0.05)
  cineSeq:Do(PushBridge)
  cineSeq:WaitForFunctionTrue(IsBridgeFinished)
  cineSeq:Do(SerpentPushComplete)
  cineSeq:Do(game.Cinematics.DisableCinematicMode)
  cineSeq:Do(function()
    GameObjects.CA_snakeLeaving.LuaObjectScript.Enable()
  end)
  cineSeq:Do(function()
    game.AI.FindSon():TriggerMoveEvent("kLE_BridgePushComplete")
  end)
  cineSeq:Do(function()
    timers.StartLevelTimer(10, UpdateCompassMarkers)
  end)
  cineSeq:Do(function()
    if game.Compass.OnWarp then
      game.Compass.OnWarp()
    end
  end)
  cineSeq:WaitSeconds(7)
  cineSeq:Do(function()
    if cineSeq.skipping then
      player:Warp(engine.Vector.New(94.818, 14.73, 54.048), player:GetWorldForward())
      game.AI.FindSon():Warp(engine.Vector.New(95.818, 14.73, 54.048), game.AI.FindSon():GetWorldForward())
    end
  end)
  cineSeq:Do(function()
    GameObjects.CA_snakeLeaving.LuaObjectScript.Disable()
  end)
  cineSeq:Do(function()
    GameObjects.CA_waterLevelDropping.LuaObjectScript.Enable()
  end)
  cineSeq:WaitSeconds(1.5)
  cineSeq:Do(function()
    cineSeq:EndSkipIfActive()
  end)
  cineSeq:Do(PlayWaterDroppingBanter)
  cineSeq:WaitSeconds(9.5)
  cineSeq:Do(function()
    GameObjects.CA_waterLevelDropping.LuaObjectScript.Disable()
  end)
  cineSeq:WaitSeconds(4)
  cineSeq:EndPOIMoment()
  cineSeq:Do(EnableElevatorAndHorn)
  cineSeq:Do(StartQuest_STN_Parent)
  cineSeq:StartSequence()
end
function PlayWaterDroppingBanter()
  game.Audio.PlayBanter("031_SpecialChisel")
end
function CanSeqFire()
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  return cineNumber < 340 and 330 <= cineNumber
end
function IsBridgeFinished()
  GetCal100()
  if cal100 ~= nil and bridgeObj == nil then
    bridgeObj = cal100:FindSingleGameObject("calderaBridge")
  end
  if bridgeObj ~= nil then
    return bridgeObj.AnimFrame == LD.GetRealmInfo().frames.Helheim
  end
  return false
end
function DisableElevatorAndHorn()
  GetCal100()
  if cal100 ~= nil then
    cal100:CallScript("Horn_DisableElevator")
    cal100:CallScript("Horn_Disable")
  end
end
function EnableElevatorAndHorn()
  GetCal100()
  if cal100 ~= nil then
    cal100:CallScript("SerpentPushComplete")
    cal100:CallScript("Horn_Enable")
  end
end
function SerpentPushComplete()
  PlayShake_BridgeSettle()
  camOneShot_Snake_015 = CCOS.OneShotCamera.New("PLYR_Nar_SnakePush_015", 7)
  camOneShot_Snake_020 = CCOS.OneShotCamera.New("PLYR_Nar_SnakePush_020", 9)
  camOneShot_Snake_030 = CCOS.OneShotCamera.New("PLYR_Nar_SnakePush_030", 13)
  camOneShot_Snake_040 = CCOS.OneShotCamera.New("PLYR_Nar_SnakePush_040", 17)
  camOneShot_Snake_040:SetCallback(EndWaterdropPOI)
  camOneShot_Snake_015:Start()
  camOneShot_Snake_020:Start()
  camOneShot_Snake_030:Start()
  camOneShot_Snake_040:Start()
  GetCal100()
  if cal100 ~= nil then
    timers.StartLevelTimer(4, cal100:CallScript("HideSnakePushCameraZone"))
  end
  local cal080 = game.FindLevel("Cal080_Global")
  cal080:CallScript("UpdateBoatDocks")
end
function EndWaterdropPOI()
  camOneShot_Snake_015 = nil
  camOneShot_Snake_020 = nil
  camOneShot_Snake_030 = nil
  camOneShot_Snake_040 = nil
  game.SubObject.Sleep(thisObj)
end
function SetupSnake()
  local jointFace = thisObj:GetWorldJointForward(thisObj:GetJointIndex(mSStartJointStr))
  local jointPos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex(mSStartJointStr))
  GetCal200()
  if cal200 then
    cal200:GetGameObject("SnakeIdle"):CallScript("SetSnakeCineFrame", jointPos, jointFace, "serpentTranslate")
  end
end
function AnimateSnake()
  local jointFace = thisObj:GetWorldJointForward(thisObj:GetJointIndex(mSStartJointStr))
  local jointPos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex(mSStartJointStr))
  GetCal200()
  if cal200 then
    cal200:GetGameObject("SnakeIdle"):CallScript("PlaySnakeCine", jointPos, jointFace, "serpentTranslate", "awake")
  end
end
function ShowSnakeAndHideIdleMesh()
  GetCal200()
  if cal200 then
    cal200:GetGameObject("SnakeIdle"):CallScript("ShowSnakeAfterSleeping")
  end
end
function PushBridge()
  LD.SetBridgePosition("Helheim")
  GetCal100()
  if cal100 ~= nil then
    cal100:CallScript("SetSerpentPush")
  end
end
function ThorStatueBreak()
  GetCal200()
  if cal200 then
    cal200:CallScript("HideRuinsSnake")
  end
  thorStatue.LuaObjectScript.StartStatueAnim()
end
function ReplaceBrokenThorStatue()
  GetCal200()
  if cal200 then
    cal200:CallScript("ShowBrokenThor")
  end
  thorStatue:Hide()
end
function GetCal100()
  if cal100 == nil then
    cal100 = game.FindLevel("Cal100_Hub")
  end
end
function EnableElevatorCA()
  local cal100 = game.FindLevel("Cal100_Hub")
  if cal100 ~= nil then
    cal100:CallScript("EnableHornElevatorCA")
  end
end
function GetCal200()
  if cal200 == nil then
    cal200 = game.FindLevel("Cal200_Shore")
  end
end
function StartQuest_STN_Parent()
  game.QuestManager.ProposeQuestState("Quest_PeaksPass_Objective742", "Complete")
  LD.ActivateQuest("Quest_StoneMason_Parent")
  game.Compass.SetGatewayMarkerIsOpen("CALS_200_Bridge7", false)
  game.Compass.SetGatewayMarkerIsOpen("CALS_200_Helper47", false)
  local hasJournalEntry = game.Wallets.GetResourceValue("HERO", "Tryptich_Jormungandr")
  if hasJournalEntry == 1 then
    LD.UpdateJournal("Tryptich_Jormungandr_PostBoat", 0)
  end
  local bookmarks = require("design.Bookmarks")
  local tableEntry = bookmarks["BOOKMARK_" .. "13_Caldera_020_WaterDrop02"]
  game.World.StoreCheckpointAndBookmark(tableEntry)
end
function UpdateCompassMarkers()
  GetCal200()
  if cal200 then
    cal200:CallScript("SetBridgeAlignment")
    cal200:CallScript("SnakeTranslateCompassClose")
  end
end
function RecenterCameraOnBridgePushStart()
  game.Camera.Recenter({
    TimeStart = 0,
    TimeDuration = 9,
    YawRange = -1,
    TriggerLeft = 150,
    TriggerRight = 150,
    ReturnLeft = 150,
    ReturnRight = 150,
    ReturnUp = -1,
    ReturnDown = -1,
    LockRecenter = 0.8,
    RotationSpace = 1
  })
end
function PlayShake_BridgeSettle()
  game.Blender.Trigger({
    Name = "FSE_SHAKE_GENERIC_GIANT",
    Duration = 0.8,
    TweenIn = {Time = 0},
    TweenOut = {Time = 2.2},
    Priority = 2000,
    Weight = 0.36
  })
  game.Blender.Trigger({
    Name = "FFB_GENERIC_RUMBLE_STRONG",
    Duration = 0.5,
    TweenIn = {Time = 0},
    TweenOut = {Time = 1.2},
    Priority = 2000
  })
end
