local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local thisObj, thisLevel
local isEnabled = false
local isLooping = false
local autoToggleVisibility = true
local cycleDelayMin = 0
local cycleDelayMax = 0
local cycleTimer, animation
local animSpeed = 1
local master
local pawns = {}
local isBoatLoot = false
local pointPrecision = 100
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  isEnabled = obj:GetLuaTableAttribute("StartEnabled")
  isLooping = obj:GetLuaTableAttribute("CycleAnim")
  autoToggleVisibility = obj:GetLuaTableAttribute("ToggleVisibilityWithEnable")
  cycleDelayMin = tonumber(obj:GetLuaTableAttribute("CycleDelayMin"))
  cycleDelayMax = tonumber(obj:GetLuaTableAttribute("CycleDelayMax"))
  animation = obj:GetLuaTableAttribute("Animations")
  animSpeed = obj:GetLuaTableAttribute("AnimSpeed")
  isBoatLoot = obj:GetLuaTableAttribute("BoatLootController")
  local pawnGroups = obj:GetLuaTableAttribute("PawnGroup")
  if pawnGroups and pawnGroups ~= "" then
    pawnGroups = LD.ConvertStringListToTable(pawnGroups)
    pawns = thisLevel:GetGameObject(pawnGroups[1]).Children
    for i = 2, #pawnGroups do
      local groupChildren = thisLevel:GetGameObject(pawnGroups[i]).Children
      for _, v in ipairs(groupChildren) do
        table.insert(pawns, v)
      end
    end
  end
  local additionalPawns = obj:GetLuaTableAttribute("AdditionalPawnObjects")
  if additionalPawns and additionalPawns ~= "" then
    additionalPawns = LD.ConvertStringListToTable(additionalPawns)
    for _, v in ipairs(additionalPawns) do
      table.insert(pawns, thisLevel:GetGameObject(v))
    end
  end
  master = obj:GetLuaTableAttribute("OptionalExternalMaster")
  if master and master ~= "" then
    master = thisLevel:GetGameObject(master).Child
  else
    master = nil
  end
  if 0 < #pawns and not master then
    master = pawns[1].Child
    table.remove(pawns, 1)
  end
  game.SubObject.Sleep(thisObj)
end
function OnStart(level, obj)
  if not master then
    return
  end
  if isBoatLoot then
    Disable()
    return
  end
  if cycleDelayMin < 0 then
    cycleDelayMin = 0
  end
  if cycleDelayMax < cycleDelayMin then
    cycleDelayMax = cycleDelayMin
  end
  if 0 < cycleDelayMax then
    cycleDelayMin = cycleDelayMin * pointPrecision
    cycleDelayMax = cycleDelayMax * pointPrecision
  end
  local i
  for i = 1, #pawns do
    if pawns[i] == master or pawns[i] == thisObj then
      table.remove(pawns, i)
      i = i - 1
    else
      pawns[i].Child:ClonePose(master)
    end
  end
  if isEnabled then
    Enable()
  else
    Disable()
  end
end
function BoatLootControllerSelected()
  if not master then
    return
  end
  if cycleDelayMin < 0 then
    cycleDelayMin = 0
  end
  if cycleDelayMax < cycleDelayMin then
    cycleDelayMax = cycleDelayMin
  end
  if 0 < cycleDelayMax then
    cycleDelayMin = cycleDelayMin * pointPrecision
    cycleDelayMax = cycleDelayMax * pointPrecision
  end
  local i
  for i = 1, #pawns do
    if pawns[i] == master or pawns[i] == thisObj then
      table.remove(pawns, i)
      i = i - 1
    else
      pawns[i].Child:ClonePose(master)
    end
  end
  Enable()
end
function OnSaveCheckpoint(level)
  return {isEnabled = isEnabled}
end
function OnRestoreCheckpoint(level, go, tab)
  isEnabled = tab.isEnabled
end
function GetMaster()
  return master
end
function Enable()
  if not animation or not master then
    return
  end
  isEnabled = true
  master:ClearAllAnimCallbacks()
  if cycleDelayMax == 0 and isLooping then
    master:PlayAnimationCycle({Animation = animation, Rate = animSpeed})
  else
    PlayAnimation()
  end
  if autoToggleVisibility then
    master:Show()
    for _, v in ipairs(pawns) do
      v:Show()
    end
  end
end
function LoopAnim()
  local randTime = math.random(cycleDelayMin, cycleDelayMax) / pointPrecision
  cycleTimer = timers.StartLevelTimer(randTime, PlayAnimation)
end
function PlayAnimation()
  if 0 < animSpeed then
    master:JumpAnimationToPercent(0, {Animation = animation})
  else
    master:JumpAnimationToPercent(1, {Animation = animation})
  end
  master:PlayAnimationToEnd({Animation = animation, Rate = animSpeed})
  if isLooping then
    master:OnAnimationDone(thisObj, "LoopAnim", {Animation = animation, Force = true})
  else
    master:OnAnimationDone(thisObj, "Disable", {Animation = animation, Force = true})
  end
end
function Disable()
  isEnabled = false
  if not animation or not master then
    return
  end
  if cycleTimer then
    cycleTimer:Stop()
  end
  master:PauseAnim()
  master:ClearAllAnimCallbacks()
  if autoToggleVisibility then
    master:Hide()
    for _, v in ipairs(pawns) do
      v:Hide()
    end
  end
end
