local LD = require("design.LevelDesignLibrary")
local actor = require("narrative.actor")
local ND = require("design.NarrativeDesignLibrary")
local timers = require("level.timer")
local thisObj, thisLevel, player, kraActor, sonActor, freActor, bifrostProp, ltw_son, ltw_freya
local cinematicStarted = false
local bStartOnSpawn = true
local lingerTimer
local tableLingerBanter = {
  "RealmTravelIntro_Linger",
  "RealmTravelIntro_Linger2",
  "RealmTravelIntro_Linger3"
}
local freyaAtRootBridge = false
local rootBridgeIsExtended = false
local alfDoor, cine_lights
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  game.SubObject.Sleep(obj)
end
function OnStart(level, obj)
  local LTWStage = game.Level.GetVariable("FreyaLTWStage")
  SetupProps()
  SetupLights()
  if 70 < LTWStage then
    DisableAllIntroLTW()
    if LTWStage == 80 then
      rootBridgeIsExtended = true
      SetupFreRealmTravelExit()
    end
  else
    SetupActors()
  end
  if LTWStage == 70 and bStartOnSpawn then
    SetupRealmTravelIntro()
  end
end
function OnSaveCheckpoint(level, obj)
  return {bStartOnSpawn = bStartOnSpawn}
end
function OnRestoreCheckpoint(level, obj, tab)
  bStartOnSpawn = tab.bStartOnSpawn
end
function SpawnFreya()
  local freObj = LD.FindFreya()
  if freObj == nil then
    local freWad = game.FindLevel("FreyaLvl100_Global")
    local jointFace = thisObj:GetWorldJointForward(thisObj:GetJointIndex("RealmTravelIntroEnter_FreyaStart"))
    local jointPos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("RealmTravelIntroEnter_FreyaStart"))
    freObj = game.AI.Spawn(freWad, jointPos, jointFace, "CRT_Freya00")
  end
  return freObj
end
function SetupActors()
  kraActor = actor.Actor.New("REALM TRAVEL INTRO: Kratos Actor", game.Player.FindPlayer)
  sonActor = actor.Actor.New("REALM TRAVEL INTRO: Son Actor", game.AI.FindSon)
  freActor = actor.Actor.New("REALM TRAVEL INTRO: Freya Actor")
  freActor:SetSpawnFunction(SpawnFreya)
end
function SetupProps()
  bifrostProp = GameObjects.bifrost00Prop.Child
  HideProps()
  ltw_son = GameObjects.LTW_RealmTravelIntro_Son
  ltw_freya = GameObjects.LTW_RealmTravelIntro_Freya
end
function ShowProps()
  bifrostProp:Show()
end
function HideProps()
  bifrostProp:Hide()
end
function ReplaceBifrostProp()
  HideProps()
  LD.GiveBifrost()
end
function SetupLights()
  cine_lights = GameObjects.Cine_Start_190a
  HideCineLights()
end
function PlayCineLights()
  cine_lights:Show()
  cine_lights:JumpAnimToFrame(0)
  cine_lights:PlayAnimToEnd()
end
function HideCineLights()
  cine_lights:Hide()
end
function SetupRealmTravelIntro()
  bStartOnSpawn = true
  SetupPOIMomentSeq()
  SetupSonEnterSeq()
  SetupFreyaEnterSeq()
end
function SetupPOIMomentSeq()
  local poiMomentSeq = ND.CreateCineSequence(thisLevel, thisObj, "Realm Travel Intro Son Enter Seq ")
  poiMomentSeq:StartPOIMoment(1.74)
  poiMomentSeq:WaitForActorPlayingMove(kraActor, "MOV_RealmTravelIntroCine")
  poiMomentSeq:EndPOIMoment()
  poiMomentSeq:StartSequence()
end
function SetupSonEnterSeq()
  local sonEnterSeq = ND.CreateCineSequence(thisLevel, thisObj, "Realm Travel Intro Son Enter Seq ")
  sonEnterSeq:Do(StartSonLTW)
  sonEnterSeq:WaitForActorInZone(sonActor, "POI_RealmTravelIntroEnter_Son")
  sonEnterSeq:Do(ltw_son.LuaObjectScript.Disable)
  sonEnterSeq:ActorForceApproachAndWait(sonActor, {
    Branch = "BRA_RealmTravelIntroEnter",
    ReferenceJoint = "RealmTravelIntro_SynchJoint",
    speed = ND.SonJogSpeed,
    stop = false,
    foot = game.Creature.Foot.kRight,
    radius = ND.SonJogArrivalRadius
  })
  sonEnterSeq:ActorSync(sonActor, {
    Branch = "BRA_RealmTravelIntroEnter",
    ReferenceJoint = "RealmTravelIntro_SynchJoint"
  })
  sonEnterSeq:StartSequence()
end
function StartSonLTW()
  GameObjects.RealmTravelIntroPathing_Son:Show()
  ltw_son.LuaObjectScript.Enable()
end
function StartFreyaLTW()
  GameObjects.RealmTravelIntroPathing_Freya:Show()
  ltw_freya.LuaObjectScript.Enable()
  GameObjects.YouShallNotPass_RealmTravelIntro.LuaObjectScript.Enable()
end
function EndFreyaLTW()
  ltw_freya.LuaObjectScript.Disable()
  GameObjects.YouShallNotPass_RealmTravelIntro.LuaObjectScript.Disable()
end
function DisableAllIntroLTW()
  ltw_son.LuaObjectScript.Disable()
  ltw_freya.LuaObjectScript.Disable()
  GameObjects.YouShallNotPass_RealmTravelIntro.LuaObjectScript.Disable()
  GameObjects.RealmTravelIntroPathing_Son:Hide()
  GameObjects.RealmTravelIntroPathing_Freya:Hide()
  bStartOnSpawn = false
end
function DisableAbandon()
  GameObjects.FXCal130Freya:Hide()
end
function SetupFreyaEnterSeq()
  local freyaEnterSeq = ND.CreateCineSequence(thisLevel, thisObj, "Realm Travel Intro Freya Enter Seq ")
  local slaveTab = {
    {
      Obj = bifrostProp,
      Anim = "poiCalRealmTravelIntro030IntFreyaEnter"
    }
  }
  freyaEnterSeq:WaitForLoadCheck("FreyaLvl100_Global")
  freyaEnterSeq:SpawnActorAndWait(freActor)
  freyaEnterSeq:Do(StartFreyaLTW)
  freyaEnterSeq:WaitForActorInZone(freActor, "POI_RealmTravelIntroEnter_Freya")
  freyaEnterSeq:Do(EndFreyaLTW)
  freyaEnterSeq:ActorForceApproachAndWait(freActor, {
    Branch = "BRA_RealmTravelIntroEnter",
    ReferenceJoint = "RealmTravelIntro_SynchJoint",
    speed = ND.FreyaWalkSpeed,
    stop = false,
    radius = ND.SonWalkArrivalRadius,
    prevent_path_eval = true
  })
  freyaEnterSeq:Do(ShowProps)
  freyaEnterSeq:ActorSync(freActor, {
    Slaves = slaveTab,
    Branch = "BRA_RealmTravelIntroEnter",
    ReferenceJoint = "RealmTravelIntro_SynchJoint",
    ReferenceObject = thisObj
  })
  freyaEnterSeq:WaitForActorFinishMove(freActor, "MOV_RealmTravelIntroEnter")
  freyaEnterSeq:Do(function()
    GameObjects.realm_controller_object.LuaObjectScript.GetInteract():SetXZRange(2)
  end)
  freyaEnterSeq:StartSequence()
end
function SonTableIdle()
  sonActor:GetActivePuppeteer():StartBranch("BRA_RealmTravelIntroLeaveSpectacle")
end
function SonExit()
  sonActor:GetActivePuppeteer():StartBranch("BRA_RealmTravelIntroExit")
end
function SetupCineSeq()
  local seq = LD.CreateCineSequence(thisLevel, thisObj, "Realm Travel Intro Cine")
  local slaveTab = {
    {Actor = freActor},
    {
      Obj = bifrostProp,
      Anim = "poiCalRealmTravelIntro050CineScene"
    }
  }
  seq:SetPostSkipMusic("SND_MX_CAL_start_master", "SND_MX_SonSick_master", "SND_MX_CAL_snake_belly_master")
  seq:MarkAbleToSkip()
  seq:Do(NotifyCineStart)
  seq:Do(DisableAllIntroLTW)
  seq:WaitForLoadCheck("FreyaLvl100_Global")
  seq:SpawnActorAndWait(freActor)
  seq:WaitForFunctionTrue(function()
    return LD.FindFreya() ~= nil
  end)
  seq:Do(game.Cinematics.EnableCinematicMode)
  seq:Do(ShowProps)
  seq:ActorForceApproachAndWait(kraActor, {
    Branch = "BRA_RealmTravelIntroCine",
    ReferenceJoint = "RealmTravelIntro_SynchJoint",
    speed = ND.KraWalkSpeed,
    stop = false,
    radius = ND.InteractStopDistance,
    weapon_state = "bare"
  })
  seq:ActorSync(kraActor, {
    Slaves = slaveTab,
    Branch = "BRA_RealmTravelIntroCine",
    ReferenceJoint = "RealmTravelIntro_SynchJoint"
  })
  seq:Do(PlayCineLights)
  seq:ActorSync(sonActor, {
    Branch = "BRA_RealmTravelIntroCine",
    ReferenceJoint = "RealmTravelIntro_SynchJoint"
  })
  seq:WaitForFunctionTrue(function()
    return player:IsPlayingMove("MOV_TravelTableIntroSpectacle")
  end)
  seq:WaitUntilActorAnimPastPercentage(kraActor, 0.17)
  seq:Do(ReplaceBifrostProp)
  seq:WaitUntilActorAnimPastFrame(kraActor, 2465)
  seq:Do(SonTableIdle)
  seq:WaitForFunctionTrue(function()
    return not player:IsPlayingMove("MOV_TravelTableIntroSpectacle")
  end)
  seq:Do(HideCineLights)
  seq:Do(Tutorial_Start)
  seq:Do(game.Cinematics.DisableCinematicMode)
  seq:StopPuppetingActor(kraActor)
  seq:WaitSeconds(1)
  seq:Do(function()
    seq:EndSkipIfActive()
  end)
  seq:Do(function()
    game.Audio.PlayBanter("RealmTravelIntro_AfterSpectacle", Tutorial_EnableRotationInput)
  end)
  seq:WaitForFunctionTrue(function()
    return LD.GetSelectedRealm() == "Jotunheim"
  end)
  seq:Do(Tutorial_DisableRotationInput)
  seq:Do(function()
    game.Audio.PlayBanter("RealmTravelIntro_Turns", Tutorial_EnableRotationInput)
  end)
  seq:WaitForFunctionTrue(function()
    return LD.GetSelectedRealm() == "Alfheim"
  end)
  seq:Do(Tutorial_DisableRotationInput)
  seq:Do(function()
    game.Audio.PlayBanter("RealmTravelIntro_AlfheimSelected", Tutorial_EnableConfirmationInput)
  end)
  seq:WaitForActorPlayingMove(kraActor, "MOV_TravelTableConfirm_RealmTravel")
  seq:Do(function()
    game.Audio.PlayBanter("RealmTravelIntro_AlfheimConfirm")
  end)
  seq:Do(function()
    game.Audio.StartMusic("SND_MX_CAL_realm_travel_first_time")
  end)
  seq:StopPuppetingActor(freActor)
  seq:Do(SonExit)
  seq:Do(SetupFreExitSeqFromRealmTravelIntro)
  seq:WaitSeconds(3)
  seq:StopPuppetingActor(sonActor)
  seq:Do(DisableAbandon)
  seq:StartSequence()
end
local kraNotCaughtUp = true
function FreyaGetToBridge()
  if game.Level.GetVariable("FreyaLTWStage") == 70 then
    StartRootBridgeAnim()
    if kraNotCaughtUp then
      FreyaEnterWaitGate()
      freyaAtRootBridge = true
    else
      PlayRootBridgeBanter()
    end
  end
end
function PlayRootBridgeBanter()
  game.Audio.PlayBanter("RealmTravelRoom2_Roots", StartRoomLingerTimers)
end
function FreyaExitWaitGate()
  local freya = LD.FindFreya()
  if freya ~= nil then
    freya:CallScript("WaitGateExit")
    kraNotCaughtUp = false
    if freyaAtRootBridge then
      PlayRootBridgeBanter()
      freyaAtRootBridge = false
    end
  end
end
function StartRootBridgeAnim()
  local cal130 = game.FindLevel("Cal130_TempleInt")
  local controllerObjectRef = cal130:FindSingleGameObject("realm_controller_object")
  controllerObjectRef:CallScript("Callscript_AnimateRootBridge_Intro")
end
function StartRoomLingerTimers()
  LD.CallFunctionAfterDelay(PlayRoomLinger, 15)
  LD.CallFunctionAfterDelay(PlayRoomLinger2, 45)
end
function PlayRoomLinger()
  if not cinematicStarted then
    game.Audio.PlayBanter("RealmTravelRoom2_Linger")
  end
end
function PlayRoomLinger2()
  if not cinematicStarted then
    game.Audio.PlayBanter("RealmTravelRoom2_Linger2")
  end
end
function NotifyCineStart()
  cinematicStarted = true
  game.World.DisablePlayerStateSoftSave()
end
function Tutorial_Start()
  if player:HasMarker("travelTutorial_Active") == false then
    player:AddMarker("travelTutorial_Active")
  end
  GameObjects.realm_controller_object.LuaObjectScript.UI_Open_RT_Menu()
end
function Tutorial_EnableRotationInput()
  if player:HasMarker("travelTutorial_Rotate") == false then
    player:AddMarker("travelTutorial_Rotate")
  end
  LD.CallFunctionAfterDelay(function()
    GameObjects.realm_controller_object.LuaObjectScript.UI_Update_RT_Menu()
  end, 0.5)
  SetupTableLinger()
end
function Tutorial_DisableRotationInput()
  if player:HasMarker("travelTutorial_Rotate") then
    player:RemoveMarker("travelTutorial_Rotate")
  end
  LD.CallFunctionAfterDelay(function()
    GameObjects.realm_controller_object.LuaObjectScript.UI_Update_RT_Menu()
  end, 0.5)
  DisableTableLinger(false)
end
function Tutorial_EnableConfirmationInput()
  if player:HasMarker("travelTutorial_Confirm") == false then
    player:AddMarker("travelTutorial_Confirm")
  end
  LD.CallFunctionAfterDelay(function()
    GameObjects.realm_controller_object.LuaObjectScript.UI_Update_RT_Menu()
  end, 0.5)
  DisableTableLinger(true)
end
function SetupTableLinger()
  print("Try Setup lingerTimer timer")
  if lingerTimer == nil then
    lingerTimer = timers.StartLevelTimer(10, PlayTableLinger)
    lingerTimer:Start()
    print("Start lingerTimer timer")
  else
    lingerTimer:Restart()
    print("Restart lingerTimer timer")
  end
end
function DisableTableLinger(shouldClear)
  if lingerTimer ~= nil then
    lingerTimer:Reset()
    print("Reset lingerTimer timer")
    if shouldClear then
      lingerTimer = nil
      print("Clear lingerTimer timer")
    end
  end
end
function PlayTableLinger()
  print("Try Play lingerTimer timer")
  if LD.GetSelectedRealm() ~= "Alfheim" and player:HasMarker("travelTutorial_Rotate") and 0 < #tableLingerBanter then
    game.Audio.PlayBanter(tableLingerBanter[1], SetupTableLinger)
    table.remove(tableLingerBanter, 1)
    print("Play lingerTimer timer")
  end
end
function SetupFreExitSeqFromRealmTravelIntro()
  GameObjects.worldTreeBridge00_P.LuaObjectScript.RegisterCustomCallbackOnAnimDone(RootBridgeExtendedAfterFirstUse)
  ForceFreyaIdleDuringTravel()
end
function RootBridgeExtendedAfterFirstUse()
  RootBridgeExtended()
  local fre = ND.FindFreya()
  if fre then
    fre:SetAccelerationOverride(1.5)
    fre:SetDecelerationOverride(1.5)
    fre:TriggerMoveEvent("kLE_FirstRealmTravelDone")
    SetupFreRealmTravelExit()
  end
  game.AI.FindSon():TriggerMoveEvent("kLE_FirstRealmTravelDone")
end
function ForceFreyaIdleDuringTravel()
  if not freActor then
    freActor = actor.Actor.New("Freya", ND.FindFreya)
  end
  local seq = LD.CreateCineSequence(thisLevel, GameObjects.FreyaForcedIdlePos, "Freya Idle During Realm Travel")
  seq:ActorSync(freActor, {
    Branch = "BRA_IdleWaitForAlfheim",
    ReferenceJoint = "FreyaForcedIdleSynchJoint"
  })
  seq:WaitForSyncStart(freActor:GetCreature())
  seq:StopPuppetingActor(freActor)
  seq:StartSequence()
end
function SetupFreRealmTravelExit()
  alfDoor = GameObjects.RealmTravelDoor_Alfheim:FindSingleGOByName("door_left")
  local seq = LD.CreateCineSequence(thisLevel, thisObj, "Realm Travel Exit LTW Seq")
  seq:Do(UnlockAirlock)
  seq:WaitForFunctionTrue(ND.FindFreya)
  seq:Do(TableToAlfheim)
  seq:WaitForFunctionTrue(IsAlfDoorOpen)
  seq:Do(FreyaExitWaitGate)
  seq:StartSequence()
end
function UnlockAirlock()
  local cal120 = game.FindLevel("Cal120_Airlock")
  if cal120 ~= nil then
    cal120:CallScript("UnlockDoors")
  end
end
function TableToAlfheim()
  if player:InsideZone("RealmTravelExit_FreyaUseCW") then
    ltw_freya = GameObjects.LTW_RealmTravelIntroExitCW_Freya
  else
    ltw_freya = GameObjects.LTW_RealmTravelIntroExit_Freya
  end
  ltw_freya.LuaObjectScript.Enable()
  print("TabletoAlf")
  local freyaLTW = game.FindLevel("FreyaLTW")
  if freyaLTW ~= nil then
    freyaLTW:CallScript("LTW_ExitRealmTravel")
  end
end
function RootBridgeExtended()
  FreyaExitWaitGate()
  rootBridgeIsExtended = true
end
function FreyaGetToExitDoor()
  if not IsAlfDoorOpen() then
    FreyaEnterWaitGate()
  end
end
function FreyaGetToExitBridge()
  if not rootBridgeIsExtended then
    FreyaEnterWaitGate()
  end
end
function FreyaEnterWaitGate()
  LD.FindFreya():CallScript("WaitGateEnter")
end
function LTWExitToAlfheim()
  return game.Level.GetVariable("FreyaLTWStage") == 80
end
function IsAlfDoorOpen()
  return alfDoor.AnimFrame == 220
end
