local LD = require("design.LevelDesignLibrary")
local thisObj, serpentObj, serpentTranslateLights, snakeStatueLights
local snakeCineAnims = {
  worldSnakeIntro = "narCalWorldSnakeIntro000CineScene",
  serpentTranslate = "narCalSerpentTranslate000CineScene",
  bridgePush = "narCalSerpentTranslate010PushScene",
  snakeStatue = "narCalSnakeStatue000CineScene"
}
local snakeIdleAnims = {
  underWater = "envCalSnakeHumpIdle",
  resting01 = "envCalSnakeHeadIdleResting",
  resting02 = "envCalSnakeHeadIdleResting2",
  sleeping = "envCalSnakeHeadIdleSleeping",
  awake = "envCalSnakeHeadIdleAwake",
  snakeBelly = "envCalSnakeHeadSnakeBellyIdle",
  knockedOut = "envStnSnakeHeadIdleKO"
}
local snakeIdleTable = {
  {
    IdleAnim = "underWater",
    ZeroJoint = "underWaterIdleJoint",
    MinCine = 0,
    MaxCine = 180
  },
  {
    IdleAnim = "resting01",
    ZeroJoint = "resting01IdleJoint",
    MinCine = 180,
    MaxCine = 190
  },
  {
    IdleAnim = "awake",
    ZeroJoint = "awakeIdleJoint",
    MinCine = 190,
    MaxCine = 250
  },
  {
    IdleAnim = "awake",
    ZeroJoint = "awakeIdleJoint",
    MinCine = 250,
    MaxCine = 310
  },
  {
    IdleAnim = "awake",
    ZeroJoint = "awakeIdleJoint",
    MinCine = 310,
    MaxCine = 330
  },
  {
    IdleAnim = "sleeping",
    ZeroJoint = "sleepingIdleJoint",
    MinCine = 330,
    MaxCine = 340
  },
  {
    IdleAnim = "awake",
    ZeroJoint = "awakeIdleJoint",
    MinCine = 340,
    MaxCine = 510
  },
  {
    IdleAnim = "awake",
    ZeroJoint = "awakeIdleJoint",
    MinCine = 510,
    MaxCine = 520,
    Requirement = function()
      return GetRealmTravelToJotunheimFailed() == false
    end
  },
  {
    IdleAnim = "resting02",
    ZeroJoint = "resting02IdleJoint",
    MinCine = 510,
    MaxCine = 520,
    Requirement = function()
      return GetRealmTravelToJotunheimFailed() == true
    end
  },
  {
    IdleAnim = "snakeBelly",
    ZeroJoint = "snakeBellyIdleJoint",
    MinCine = 520,
    MaxCine = 540
  }
}
local nextIdleAnim = ""
function OnScriptLoaded(level, obj)
  thisObj = obj
end
function OnStart(level, obj)
  SetupLights()
  SetupSerpent()
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  if cineNumber < 540 then
    UpdateSnakeIdle()
  end
  print("Snake Cine Check: ", cineNumber)
  if cineNumber < 180 then
    HideSnake()
  elseif 540 <= cineNumber then
    HideSnake()
    GameObjects.worldsnakeProp.Child:PauseAnim()
  end
  game.SubObject.Sleep(obj)
  game.SubObject.SetForgetOnCheckpoint(obj)
end
function HideSnake()
  print("Hiding Snake Character")
  GameObjects.worldsnakeProp.Child:Hide()
end
function ShowSnake()
  print("Showing Snake Character")
  GameObjects.worldsnakeProp.Child:Show()
end
function SetupLights()
  serpentTranslateLights = GameObjects.Cine_Start_340
  snakeStatueLights = GameObjects.Cine_Start_520
  HideLights()
end
function SetupSerpent()
  serpentObj = GameObjects.worldsnakeProp.Child
  serpentObj:AddMarker("Serpent")
  serpentObj:Show()
end
function PlayLights(cineName)
  if cineName == "serpentTranslate" then
    serpentTranslateLights:Show()
    serpentTranslateLights:JumpAnimationToFrame(0)
    serpentTranslateLights:PlayAnimationToEnd()
  elseif cineName == "snakeStatue" then
    snakeStatueLights:Show()
    snakeStatueLights:JumpAnimationToFrame(0)
    snakeStatueLights:PlayAnimationToEnd()
  end
end
function HideLights()
  serpentTranslateLights:Hide()
  snakeStatueLights:Hide()
end
function UpdateSnakeIdle(level, obj)
  local cineNumber = game.Level.GetVariable("CompletedCineNumber")
  for _, v in ipairs(snakeIdleTable) do
    if cineNumber >= v.MinCine and cineNumber < v.MaxCine then
      if v.Requirement ~= nil then
        if v.Requirement() == true then
          PlaySnakeIdle(v.IdleAnim, v.ZeroJoint)
          return
        end
      else
        PlaySnakeIdle(v.IdleAnim, v.ZeroJoint)
        return
      end
    end
  end
end
function PlaySnakeIdle(idleName, zeroJoint)
  local animName = idleName
  if animName == nil then
    animName = "awake"
  end
  if snakeIdleAnims[animName] ~= nil then
    if zeroJoint ~= nil then
      local jointFace = thisObj:GetWorldJointForward(thisObj:GetJointIndex(zeroJoint))
      local jointPos = thisObj:GetWorldJointPosition(thisObj:GetJointIndex(zeroJoint))
      serpentObj:SetWorldPosition(jointPos)
      serpentObj:SetWorldFacing(jointFace)
    end
    HideLights()
    serpentObj:PlayAnimationCycle({
      Animation = snakeIdleAnims[animName],
      Rate = 1
    })
  end
  if animName == "sleeping" then
    GameObjects.worldsnake_SleepingIdle:Show()
    serpentObj:Hide()
  else
    ShowSnakeAfterSleeping()
  end
  if animName == "snakeBelly" then
    PlaySnakeBellySounds()
  end
  if animName == "resting01" or animName == "resting02" or animName == "awake" then
    PlayIdleBreathingSound()
  end
end
function SetSnakeCineFrame(level, obj, pos, dir, cineName)
  if cineName ~= nil and snakeCineAnims[cineName] ~= nil then
    serpentObj:SetWorldPosition(pos)
    serpentObj:SetWorldFacing(dir)
    serpentObj:JumpAnimationToFrame(0, {
      Animation = snakeCineAnims[cineName]
    })
    serpentObj:PauseAnimation()
  end
end
function PlaySnakeCine(level, obj, pos, dir, cineName, idleName)
  nextIdleAnim = idleName
  if cineName ~= nil and snakeCineAnims[cineName] ~= nil then
    PlayLights(cineName)
    if cineName == "worldSnakeIntro" then
      serpentObj:StartMaterialAnim("Cal_eye_reveal")
    end
    serpentObj:SetWorldPosition(pos)
    serpentObj:SetWorldFacing(dir)
    serpentObj:StartAnim(snakeCineAnims[cineName])
    serpentObj:PlayAnimToEnd()
    if cineName == "serpentTranslate" then
      serpentObj:OnAnimDone(thisObj, "PlaySnakePush")
    else
      serpentObj:OnAnimDone(thisObj, "GotoNextIdle")
    end
  end
end
function PlaySnakePush()
  local pushAnimName = snakeCineAnims.bridgePush
  serpentObj:PlayAnimationToEnd({Animation = pushAnimName, Tween = 1})
  serpentObj:OnAnimationDone(thisObj, "GotoNextIdle", {Animation = pushAnimName, Force = true})
end
function GotoNextIdle()
  PlaySnakeIdle(nextIdleAnim)
end
function GetRealmTravelToJotunheimFailed()
  print("_GBL_RealmTravel_JotunheimFailed: ", game.Level.GetVariable("_GBL_RealmTravel_JotunheimFailed"))
  return game.Level.GetVariable("_GBL_RealmTravel_JotunheimFailed")
end
function ShowSnakeAfterSleeping()
  GameObjects.worldsnake_SleepingIdle:Hide()
  serpentObj:Show()
end
function PlaySnakeBellySounds()
  print("Playing Snake Belly Idle Sounds")
  local snakeEmitter = serpentObj:FindSingleSoundEmitterByName("SNDMouth")
  LD.PlaySound(snakeEmitter, "SND_CHR_World_Serpent_Breath_Exterior_LP")
  LD.PlaySound(snakeEmitter, "SND_CHR_World_Serpent_Exterior_Chortle_Oneshot_LP")
  local cal050 = game.FindLevel("Cal050_Sound")
  if cal050 ~= nil then
    cal050:CallScript("ShowSnakeMouthZone")
  end
end
function PlayIdleBreathingSound()
  print("Playing Snake Idle Breathing Sounds")
  local snakeEmitter = serpentObj:FindSingleSoundEmitterByName("SNDMouthObstruct")
  LD.PlaySound(snakeEmitter, "SND_CHR_World_Serpent_Breath_Exterior_LP")
end
function StopIdleBreathingSound()
  print("Stopping Snake Idle Breathing Sounds")
  local snakeEmitter = serpentObj:FindSingleSoundEmitterByName("SNDMouthObstruct")
  LD.StopSound(snakeEmitter, "SND_CHR_World_Serpent_Breath_Exterior_LP")
end
