local LD = require("design.LevelDesignLibrary")
local ND = require("design.NarrativeDesignLibrary")
local checkpoint = require("level.checkpoint")
local actor = require("narrative.actor")
local CCEC = require("camera.camera_cineentercamera")
local thisObj, thisLevel, kratosActor, sonActor, logActor, boatActor, boat, boatNoose, boatRope10_1, boatRope10_2, boatRope30, cineEnterLogBoatEnterCam, cineEnterLogBoatForceEarlyBoat
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  game.SubObject.Sleep(obj)
end
function OnStart(level, obj)
  InitializeProps()
  if game.Level.GetVariable("CompletedCineNumber") < 13 then
    SetupActors()
    SpawnBoat()
  end
end
function OnUpdate(level, obj)
  if cineEnterLogBoatEnterCam ~= nil then
    cineEnterLogBoatEnterCam:Update()
  end
  if cineEnterLogBoatForceEarlyBoat ~= nil then
    cineEnterLogBoatForceEarlyBoat:Update()
  end
end
function OnSaveCheckpoint(level, obj)
  local savedInfo = {}
  savedInfo.LevelState = checkpoint.Save()
  return savedInfo
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  checkpoint.Restore(savedInfo.LevelState)
end
function InitializeProps()
  boatNoose = GameObjects.boatNoose00Top.Child
  boatRope10_1 = GameObjects.boatRope10_1.Child
  boatRope10_2 = GameObjects.boatRope10_2.Child
  boatRope30 = GameObjects.boatRope30Top.Child
  boatNoose:StartAnim("narForLogBoatEnter000CineScene")
  boatRope10_1:StartAnim("narForLogBoatEnter000CineScene")
  boatRope10_2:StartAnim("narForLogBoatEnter000CineScene1")
  boatRope30:StartAnim("narForLogBoatEnter000CineScene")
  boatNoose:JumpAnimToFrame(0)
  boatRope10_1:JumpAnimToFrame(0)
  boatRope10_2:JumpAnimToFrame(0)
  boatRope30:JumpAnimToFrame(0)
  boatNoose:PauseAnim()
  boatRope10_1:PauseAnim()
  boatRope10_2:PauseAnim()
  boatRope30:PauseAnim()
  HideProps()
end
function HideProps()
  boatNoose:Hide()
  boatRope10_1:Hide()
  boatRope10_2:Hide()
  boatRope30:Hide()
end
function ShowProps()
  boatNoose:Show()
  boatRope10_1:Show()
  boatRope10_2:Show()
  boatRope30:Show()
end
function SetupActors()
  kratosActor = actor.Actor.New("LOG BOAT ENTER: Kratos Actor", game.Player.FindPlayer)
  sonActor = actor.Actor.New("LOG BOAT ENTER: Son Actor", game.AI.FindSon)
  logActor = actor.Actor.New("LOG BOAT ENTER: Log Actor", FindLog)
  boatActor = actor.Actor.New("LOG BOAT ENTER: Boat Actor")
end
function FindLog()
  local logObjs = game.World.FindGameObjectsByMarker("log00")
  if logObjs then
    return logObjs[1]
  else
    error("Log not found to sync with boat for LogBoatEnter")
  end
end
function SpawnBoat()
  local boat_Start = LD.GetWorldJointPosition("Cine_SpawnBoat", "Boat_SpawnJoint")
  local boat_Start_Fwd = LD.GetWorldJointForward("Cine_SpawnBoat", "Boat_SpawnJoint")
  boatActor:SetAsyncSpawn(thisLevel, boat_Start, boat_Start_Fwd, "CRT_Boat00", {branchName = "BRA_Spawn"}, function(boat)
    _G.AttachBoatRopeToVehicle(boat)
  end)
  local seq = LD.CreateCineSequence(thisLevel, thisObj, "spawn boat")
  seq:SpawnActorAndWait(boatActor)
  seq:Do(function()
    boat = boatActor:GetCreature()
    boat:AddMarker("logDock")
    local boatPuppeteerHelper = boat:FindSingleGOByName("puppeteerHelper")
    boatPuppeteerHelper.LuaObjectScript.DisableInteractZone()
    local data = {}
    data.TargetMaxSpeed = 6
    data.TargetMaxRotationSpeed = 100
    data.TargetAcceleration = 17.5
    data.TargetAngularAcceleration = 115
    data.MaxSpeedChangeRate = 100
    data.MaxRotationSpeedChangeRate = 10000
    data.AccelerationChangeRate = 100
    data.AngularAccelerationChangeRate = 10000
    game.Boat.SetOverrideSpeedControlData(boat, data)
  end)
  seq:StartSequence()
end
function SetupCineSequence()
  if game.Level.GetVariable("CompletedCineNumber") < 13 then
    local cineSeq = LD.CreateCineSequence(thisLevel, thisObj, "Log Boat Enter Sequence")
    local logBoatEnter_ActorTable = {
      {
        Actor = sonActor,
        Branch = "BRA_LogBoatEnter"
      },
      {
        Actor = kratosActor,
        Branch = "BRA_LogBoatEnter"
      },
      {
        Actor = logActor,
        Branch = "BRA_LogBoatEnter"
      },
      {
        Obj = boatNoose,
        Anim = "narForLogBoatEnter000CineScene"
      },
      {
        Obj = boatRope10_1,
        Anim = "narForLogBoatEnter000CineScene"
      },
      {
        Obj = boatRope10_2,
        Anim = "narForLogBoatEnter000CineScene1"
      },
      {
        Obj = boatRope30,
        Anim = "narForLogBoatEnter000CineScene"
      }
    }
    cineSeq:WaitForLoadCheck("For100_River")
    cineSeq:SetPostSkipMusic("SND_MX_PRO_start_master")
    cineSeq:MarkAbleToSkip()
    cineSeq:RequestCineModeAndWait(kratosActor, thisObj)
    cineSeq:Do(CameraStartLogBoatEnter)
    cineSeq:ActorForceApproachAndWait(kratosActor, {
      Branch = "BRA_LogBoatEnter",
      ReferenceJoint = "LogBoatEnter_SynchJoint",
      speed = 0.9,
      stop = false,
      radius = 0.1
    })
    cineSeq:Do(ShowProps)
    cineSeq:ActorSync(boatActor, {
      Slaves = logBoatEnter_ActorTable,
      Branch = "BRA_LogBoatEnter",
      ReferenceJoint = "LogBoatEnter_SynchJoint"
    })
    cineSeq:Do(function()
      GameObjects.CA_Idle_PostCine.LuaObjectScript.Disable()
    end)
    cineSeq:Do(function()
      GameObjects.LogCarry_PlayerNavCurve_010.LuaObjectScript.Disable()
    end)
    cineSeq:Do(AddBoatMarkers)
    cineSeq:WaitUntilActorAnimPastPercentage(kratosActor, 0.85)
    cineSeq:Do(CameraStartForcedBoatSubmission)
    cineSeq:WaitUntilActorAnimPastPercentage(kratosActor, 0.99999)
    cineSeq:Do(_G.ShowBoatRope)
    cineSeq:Do(HideProps)
    cineSeq:WaitForAndCompleteCineMode(kratosActor, thisObj)
    cineSeq:DespawnActor(logActor)
    cineSeq:StopPuppetingActor(kratosActor)
    cineSeq:StopPuppetingActor(sonActor)
    cineSeq:StopPuppetingActor(boatActor)
    cineSeq:Do(function()
      local boat = game.Boat.GetPlayerBoat()
      boat:FindSingleGOByName("puppeteerHelper"):CallScript("NotifyDockSystem_PlayerEnteringBoat", boat)
      local for101 = game.FindLevel("For101_RiverToHouse")
      if for101 ~= nil then
        local data = {}
        data.Boat = boat
        data.MinAngle = 25
        data.MaxAngle = 65
        for101:EnableBoatLimitedRotationControlMode(data)
      end
    end)
    cineSeq:SetCompletedCineNumber(13)
    cineSeq:Do(function()
      game.AI.FindSon():CallScript("SetOneOffTimerActivation", true)
    end)
    cineSeq:StartSequence()
  end
end
function CameraStartLogBoatEnter()
  game.SubObject.Wake(thisObj)
  GameObjects.CamZone_LogCarry_Forced_010:HideCameraVolume()
  cineEnterLogBoatEnterCam = CCEC.CineEnterCamera.New("ENV_CineEnter_narForLogBoatEnter000CineScene", 6)
  cineEnterLogBoatEnterCam:Start()
end
function CameraStartForcedBoatSubmission()
  cineEnterLogBoatForceEarlyBoat = CCEC.CineEnterCamera.New("PLYR_Boat_Log_Sequence", 6)
  cineEnterLogBoatForceEarlyBoat:SetCallback(CameraDestroyLogBoatEnter)
  cineEnterLogBoatForceEarlyBoat:Start()
end
function CameraDestroyLogBoatEnter()
  cineEnterLogBoatEnterCam = nil
  cineEnterLogBoatForceEarlyBoat = nil
  game.SubObject.Sleep(thisObj)
end
function AddBoatMarkers()
  game.Player.FindPlayer():AddMarker("logDock")
  game.AI.FindSon():AddMarker("logDock")
end
