local LD = require("design.LevelDesignLibrary")
local actor = require("narrative.actor")
local uiCalls = require("ui.uicalls")
local thisObj, thisLevel, player, son, kraActor, sonActor, boatActor, seagullProp1, seagullProp2, seagullProp3, seagullProp4, seagullProp5, seagullProp6, seagullProp7, seagullProp8, seagullProp9, worldsnakeBodyProp, snakeWave
local waterDropLightFrame = 1744
local rotFrame = 2278
local waterDropFxOnFrame = 3760
local waterDropFxTriggerFrame = 927
local inDockZone = false
local e3LightingSet = false
local gVFSE3Lighting = engine.VFSBool.New("E3 Pre Cine Lighting")
local cineLights, cineLightsOutro, cineSeq, dockScript
local banterPlayed = {}
local cineBoat, seagullSound1, seagullSound2, seagullSound3
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  cineLights = GameObjects.Cine_Start_180
  cineLightsOutro = GameObjects.Cine_Start_180B
  dockScript = GameObjects.Dock_WorldSnakeIntro.LuaObjectScript
  game.SubObject.SetForgetOnCheckpoint(obj)
end
function OnPreStart(level, obj)
  dockScript.DisableDocking()
end
function OnFirstStart(level, obj)
  HideLights()
  HideLightsOutro()
end
function OnStart(level, obj)
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if cineNumber < 180 then
    CreateActors()
  elseif cineNumber == 180 then
    GameObjects.AwareZone_StatueClose_Level_0.LuaObjectScript.DisableEventEmitter()
  end
  SetupProps()
  PlaySoundSeagullIdle()
  snakeWave = GameObjects.WorldSnakeWave.Child:FindSingleGOByName("SnakeWave")
  HideSnakeWave()
  GameObjects.BanterLookAt_AxeSacrifice_Approach.LuaObjectScript.Disable()
end
function OnUpdate(level, obj)
  if gVFSE3Lighting.value == true and not e3LightingSet and game.FindLevel("Cal200_Shore") ~= nil then
    TurnOnCineLighting()
    e3LightingSet = true
  end
  if inDockZone then
    local playerBoat = game.Boat.GetPlayerBoat()
    if playerBoat == nil then
      error("Didn't have a player boat when processing world snake intro.")
    else
      local toDockDirection = GameObjects.DockMarker:GetWorldPosition() - playerBoat:GetWorldPosition()
      toDockDirection = toDockDirection:Normalized()
      local dockFacing = GameObjects.Dock_WorldSnakeIntro:GetWorldLeft()
      local boatFacing = playerBoat:GetWorldForward()
      if toDockDirection:Dot(dockFacing) > 0.7071 and boatFacing:Dot(dockFacing) > 0.2588 then
        dockScript.EnableDocking()
      else
        dockScript.DisableDocking()
      end
    end
  else
    dockScript.DisableDocking()
  end
end
function CreateActors()
  kraActor = actor.Actor.New("KRATOS", game.Player.FindPlayer)
  sonActor = actor.Actor.New("SON", game.AI.FindSon)
  boatActor = actor.Actor.New("BOAT", game.Boat.GetPlayerBoat)
end
function SetupProps()
  seagullProp1 = thisObj:FindSingleGOByName("seagullProp1").Child
  seagullProp2 = thisObj:FindSingleGOByName("seagullProp2").Child
  seagullProp3 = thisObj:FindSingleGOByName("seagullProp3").Child
  seagullProp4 = thisObj:FindSingleGOByName("seagullProp4").Child
  seagullProp5 = thisObj:FindSingleGOByName("seagullProp5").Child
  seagullProp6 = thisObj:FindSingleGOByName("seagullProp6").Child
  seagullProp7 = thisObj:FindSingleGOByName("seagullProp7").Child
  seagullProp8 = thisObj:FindSingleGOByName("seagullProp8").Child
  seagullProp9 = thisObj:FindSingleGOByName("seagullProp9").Child
  seagullSound1 = seagullProp1:FindSingleSoundEmitterByName("SNDSeagull")
  seagullSound2 = seagullProp2:FindSingleSoundEmitterByName("SNDSeagull")
  seagullSound3 = seagullProp3:FindSingleSoundEmitterByName("SNDSeagull")
  worldsnakeBodyProp = GameObjects.worldsnakeBodyProp.Child
  seagullProp4:Hide()
  seagullProp5:Hide()
  seagullProp6:Hide()
  seagullProp7:Hide()
  seagullProp8:Hide()
  seagullProp9:Hide()
  worldsnakeBodyProp:Hide()
  IdleGulls()
end
function HideProps()
  seagullProp1:Hide()
  seagullProp2:Hide()
  seagullProp3:Hide()
  seagullProp4:Hide()
  seagullProp5:Hide()
  seagullProp6:Hide()
  seagullProp7:Hide()
  seagullProp8:Hide()
  seagullProp9:Hide()
  worldsnakeBodyProp:Hide()
end
function ShowProps()
  seagullProp1:Show()
  seagullProp2:Show()
  seagullProp3:Show()
  seagullProp4:Show()
  seagullProp5:Show()
  seagullProp6:Show()
  seagullProp7:Show()
  seagullProp8:Show()
  seagullProp9:Show()
  worldsnakeBodyProp:Show()
end
function HideSnakeWave()
  snakeWave:Hide()
end
function IdleGulls()
  seagullProp1:StartAnim("narCalWorldSnakeIntro000BirdIdle")
  seagullProp1:PlayAnimOscillate()
  seagullProp2:StartAnim("narCalWorldSnakeIntro000BirdIdle1")
  seagullProp2:PlayAnimOscillate()
  seagullProp3:StartAnim("narCalWorldSnakeIntro000BirdIdle2")
  seagullProp3:PlayAnimOscillate()
end
function SetupWorldSnakeIntroSeq()
  cineSeq = LD.CreateCineSequence(thisLevel, thisObj, "World Snake Intro")
  local actorTable = {
    {
      Actor = sonActor,
      Branch = "BRA_WorldSnakeIntro"
    },
    {
      Actor = kraActor,
      Branch = "BRA_WorldSnakeIntro"
    },
    {
      Obj = seagullProp1,
      Anim = "narCalWorldSnakeIntro000CineScene"
    },
    {
      Obj = seagullProp2,
      Anim = "narCalWorldSnakeIntro000CineScene1"
    },
    {
      Obj = seagullProp3,
      Anim = "narCalWorldSnakeIntro000CineScene2"
    },
    {
      Obj = seagullProp4,
      Anim = "narCalWorldSnakeIntro000CineScene3"
    },
    {
      Obj = seagullProp5,
      Anim = "narCalWorldSnakeIntro000CineScene4"
    },
    {
      Obj = seagullProp6,
      Anim = "narCalWorldSnakeIntro000CineScene5"
    },
    {
      Obj = seagullProp7,
      Anim = "narCalWorldSnakeIntro000CineScene6"
    },
    {
      Obj = seagullProp8,
      Anim = "narCalWorldSnakeIntro000CineScene7"
    },
    {
      Obj = seagullProp9,
      Anim = "narCalWorldSnakeIntro000CineScene8"
    },
    {
      Obj = worldsnakeBodyProp,
      Anim = "narCalWorldSnakeIntro000CineScene2"
    }
  }
  cineSeq:SetPostSkipMusic("SND_MX_RIV_start_master", "SND_MX_SonSick_master", "SND_MX_CAL_snake_belly_master")
  cineSeq:MarkAbleToSkip()
  cineSeq:Do(function()
    cineBoat = game.Boat.GetPlayerBoat()
  end)
  cineSeq:Do(DisableSetup)
  cineSeq:Do(LD.Trigger_WaterDrop01)
  cineSeq:Do(RemoveBoatContext)
  cineSeq:Do(ShowProps)
  cineSeq:Do(game.Cinematics.EnableCinematicMode)
  cineSeq:ActorSync(boatActor, {
    Slaves = actorTable,
    Branch = "BRA_WorldSnakeIntro",
    ReferenceJoint = "WorldSnakeIntro_SynchJoint"
  })
  cineSeq:Do(AnimateSnake)
  cineSeq:Do(AnimateWave)
  cineSeq:Do(PlayLights)
  cineSeq:WaitUntilActorAnimPastFrame(kraActor, waterDropLightFrame)
  cineSeq:Do(WaterLevelOneSetupDuringCine)
  cineSeq:WaitUntilActorAnimPastFrame(kraActor, rotFrame)
  cineSeq:Do(SnapBridgeToMidgard)
  cineSeq:WaitUntilActorAnimPastPercentage(kraActor, 0.72)
  cineSeq:Do(DisplayEitrImbued)
  cineSeq:WaitUntilActorAnimPastFrame(kraActor, waterDropFxOnFrame)
  cineSeq:Do(function()
    local cal200 = game.FindLevel("Cal200_Shore")
    cal200:FindSingleGameObject("waterdropfx_manager"):CallScript("EnableFX")
  end)
  cineSeq:WaitForFunctionTrue(function()
    return not kraActor:GetCreature():IsPlayingMove("MOV_WorldSnakeIntro")
  end)
  cineSeq:Do(HideProps)
  cineSeq:Do(ShopIntroOn)
  cineSeq:WaitForFunctionTrue(function()
    return kraActor:GetCreature():IsPlayingMove("MOV_WorldSnakeOutro")
  end)
  cineSeq:Do(HideLights)
  cineSeq:Do(PlayLightsOutro)
  cineSeq:WaitUntilActorAnimPastFrame(kraActor, waterDropFxTriggerFrame)
  cineSeq:WaitUntilActorAnimPastPercentage(kraActor, 0.95)
  cineSeq:Do(function()
    cineSeq:EndSkipIfActive()
  end)
  cineSeq:Do(function()
    local cal200 = game.FindLevel("Cal200_Shore")
    cal200:FindSingleGameObject("waterdropfx_manager"):CallScript("TriggerFX")
    cal200:CallScript("ShowSnakeBlocker_WaterDrop01")
  end)
  cineSeq:WaitForFunctionTrue(function()
    return not kraActor:GetCreature():IsPlayingMove("MOV_WorldSnakeOutro")
  end)
  cineSeq:Do(HideLightsOutro)
  cineSeq:Do(HideSnakeWave)
  cineSeq:StopPuppetingActor(boatActor)
  cineSeq:StopPuppetingActor(kraActor)
  cineSeq:StopPuppetingActor(sonActor)
  cineSeq:SetCompletedCineNumber(180)
  cineSeq:Do(BanterCalderaTemple)
  cineSeq:Do(RemoveDockingMarker)
  cineSeq:Do(RiverPass_Obj935)
  cineSeq:Do(BestiaryEntry)
  cineSeq:Do(function()
    cineBoat:FindSingleGOByName("puppeteerHelper"):CallScript("EnableInteractZone")
  end)
  cineSeq:Do(game.Cinematics.DisableCinematicMode)
  cineSeq:Do(CleanupAfterCine)
  cineSeq:Do(game.World.StoreCheckpoint)
  cineSeq:StartSequence()
end
function CleanupAfterCine()
  Cal080Cleanup()
  Cal200Cleanup()
  FlagShoresAsRevealed()
end
function Cal080Cleanup()
  game.FindLevel("Cal080_Global"):CallScript("WorldSnakeIntroComplete")
end
function Cal200Cleanup()
  local cal200 = game.FindLevel("Cal200_Shore")
  cal200:CallScript("SnakeCineVolsOff")
end
function EnterDockZone()
  inDockZone = true
  if not player:HasMarker("worldSnakeIntroDocking") then
    player:AddMarker("worldSnakeIntroDocking")
  end
  if not son:HasMarker("worldSnakeIntroDocking") then
    son:AddMarker("worldSnakeIntroDocking")
  end
end
function ExitDockZone()
  inDockZone = false
end
function LeaveCineArea()
  if cineSeq == nil then
    RemoveDockingMarker()
  end
end
function RemoveDockingMarker()
  player:RemoveMarker("worldSnakeIntroDocking")
  son:RemoveMarker("worldSnakeIntroDocking")
end
function DisableSetup()
  inDockZone = false
  GameObjects.Ent_DockButton:Hide()
  dockScript.Disable()
end
function WaterLevelOneSetupDuringCine()
  local cal200 = game.FindLevel("Cal200_Shore")
  cal200:CallScript("WaterLevelOneSetupDuringCine")
end
function DisplayEitrImbued()
  uiCalls.SendSidebarDesignerMessage({
    Text = 44098,
    MessageVariant = uiCalls.msgParam.SIDEBAR_SMALL,
    DisplayTime = 2.3,
    Critical = true
  })
end
function TurnOnCineLighting()
  cineLights:Show()
  cineLights:JumpAnimationToFrame(0)
  cineLights:PauseAnimation()
end
function HideLights()
  cineLights:Hide()
end
function HideLightsOutro()
  cineLightsOutro:Hide()
end
function PlayLights()
  cineLights:Show()
  cineLights:JumpAnimationToFrame(0)
  cineLights:PlayAnimationToEnd()
end
function PlayLightsOutro()
  cineLightsOutro:Show()
  cineLightsOutro:JumpAnimationToFrame(0)
  cineLightsOutro:PlayAnimationToEnd()
end
function ShopIntroOn()
  local cal100 = game.FindLevel("Cal100_Hub")
  print("turning on ShopIntro load zone in Cal100")
  if cal100 ~= nil then
    cal100:CallScript("ShopIntroOn")
  end
end
function BanterCalderaTemple()
  game.Audio.PlayBanter("030_CalderaTemple")
end
function SnapBridgeToMidgard()
  LD.SetCurrentRealm("Midgard")
  LD.SetSelectedRealm("Midgard")
  LD.SetBridgePosition("Midgard", 0)
end
function AnimateWave()
  snakeWave:Show()
  snakeWave:JumpAnimToFrame(0)
  snakeWave:PlayAnimToEnd()
end
function AnimateSnake()
  local jointFace = thisObj:GetWorldJointForward(thisObj:GetJointIndex("WorldSnakeIntro_SynchJoint"))
  local jointPos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex("WorldSnakeIntro_SynchJoint"))
  local cal200 = game.FindLevel("Cal200_Shore")
  if cal200 then
    GameObjects.WorldSnake_Water0:Hide()
    local snakeIdle = cal200:GetGameObject("SnakeIdle")
    snakeIdle:CallScript("ShowSnake")
    snakeIdle:CallScript("PlaySnakeCine", jointPos, jointFace, "worldSnakeIntro", "resting01")
  end
end
function RemoveBoatContext()
  GameObjects.AwareZone_StatueClose_Level_0.LuaObjectScript.DisableEventEmitter()
  GameObjects.AwareZone_StatueCloser.LuaObjectScript.DisableEventEmitter()
  local cal200 = game.FindLevel("Cal200_Shore")
  son:CallScript("ClearBehaviorContext")
  if cal200 ~= nil then
    cal200:CallScript("Disable_Level1_AwarenessZones")
  end
end
function FlagShoresAsRevealed()
  LD.SetRegionDiscovered("CalderaShores")
  LD.SetRegionDiscovered("CalderaShoresA")
  LD.SetRegionDiscovered("CalderaShoresB")
  LD.SetRegionDiscovered("CalderaShoresC")
  LD.SetRegionDiscovered("CalderaShoresD")
  LD.SetRegionDiscovered("CalderaShoresE")
  LD.SetRegionDiscovered("CalderaShoresF")
  LD.SetRegionDiscovered("CalderaShoresG")
  LD.SetRegionDiscovered("CalderaShoresH")
  LD.SetRegionDiscovered("CalderaTemple")
  local upperDockTable = {
    "ISW_910_DockPoint_Upper",
    "BSW_960_DockPoint_Upper",
    "BT_970_DockPoint_Upper"
  }
  for _, dockpoint in pairs(upperDockTable) do
    game.Map.ChangeMarkerState(dockpoint, tweaks.eTokenState.kDiscovered)
  end
  LD.UpdateMap("ISW_910_DockPoint_Upper", 2)
end
function RiverPass_Obj935()
  game.QuestManager.ProposeQuestState("Quest_RiverPass_Objective935", "Complete")
  game.Compass.OnWarp()
end
function SoftSave()
  game.SubObject.SoftSave()
end
function CanPlaySeq()
  if game.Level.GetVariable("CompletedCineNumber") < 180 then
    GameObjects.Dock_WorldSnakeIntro.Child.LuaObjectScript.EnableCinematicTrigger()
  end
end
function PlayBtr_AxeSacrifice()
  Complete_Riv930()
  if game.Level.GetVariable("CompletedCineNumber") < 180 and not banterPlayed.AxeSacrifice then
    game.Audio.PlayBanterNonCritical("020_AxeSacrifice")
    banterPlayed.AxeSacrifice = true
  end
end
function EnableDock()
  GameObjects.Ent_DockButton:Show()
  GameObjects.AwareZone_StatueClose_Level_0.LuaObjectScript.DisableEventEmitter()
end
function LoadCheck()
  game.UI.LoadCheck("Cal050_Sound")
end
function Complete_Riv930()
  LD.CompleteQuest("Quest_RiverPass_Objective930")
  game.SubObject.SoftSave()
end
function BestiaryEntry()
  LD.UnlockBestiaryEntry("Bestiary_Unlock_WorldSerpent")
end
function HeadTrack_StatueCloser()
  GameObjects.EntZn_BtrBtr_AxeSacrifice:HideEntityVolume()
  GameObjects.BanterLookAt_AxeSacrifice_Approach.LuaObjectScript.Enable()
end
function Btr_StatueCloser()
  son:CallScript("ClearBehaviorContext")
end
function Btr_AxeSacrificeApproach_Done()
  EnableDock()
end
function DisableAwarenessZone()
  GameObjects.SnakeWall1_AwarenessZone_With_Headtrack.LuaObjectScript.DisableEventEmitter()
end
function OnEnterAwarenessZone()
  son:CallScript("EnterBehaviorContext", "BOAT_CONTEXT_CONFIG_LEFT")
end
function OnExitAwarenessZone()
  son:CallScript("ClearThisBehaviorContextIfActive", "BOAT_CONTEXT_CONFIG_LEFT")
end
function OnSaveCheckpoint(level, obj)
  local savedInfo = {}
  savedInfo.banterPlayed = banterPlayed
  return savedInfo
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  if savedInfo ~= nil then
    banterPlayed = savedInfo.banterPlayed
  end
end
function PlaySoundSeagullIdle()
  LD.PlayRestartableSoundLoop(seagullSound1, "SND_AMB_EMIT_Seagull_Call_LP")
  LD.PlayRestartableSoundLoop(seagullSound2, "SND_AMB_EMIT_Seagull_Call_LP")
  LD.PlayRestartableSoundLoop(seagullSound3, "SND_AMB_EMIT_Seagull_Call_LP")
end
