local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local color = require("core.color")
local thisObj
local curRuneNum = 1
local totalRuneSlots = 3
local currentState = 1
local runeTable = {}
local hasDrain
local poweredPlaySpeed = 0.75
local poweredStopTime = 0.5
local onStartRotate = {}
local onRotate = {}
local log = ""
local isDim = false
local debug_runesOn = false
function OnScriptLoaded(level, obj)
  thisObj = obj
  local isFreeStanding = obj:GetLuaTableAttribute("FreeStanding")
  poweredStopTime = obj:GetLuaTableAttribute("DrainWaitTime")
  runeTable[1] = {
    num = 1,
    frame = 0,
    snapBackframe = 105,
    runeVisual = nil
  }
  runeTable[2] = {
    num = 2,
    frame = 40,
    snapBackframe = 25,
    runeVisual = nil
  }
  runeTable[3] = {
    num = 3,
    frame = 80,
    snapBackframe = 65,
    runeVisual = nil
  }
  currentState = 1
  for i = 1, totalRuneSlots do
    runeTable[i].num = obj:FindLuaTableAttribute("RuneSlot" .. tostring(i))
    runeTable[i].runeVisual = thisObj:FindSingleGOByName("RuneGroup" .. tostring(i))
  end
  if isFreeStanding == true then
    local floorStand = obj:FindSingleGOByName("FloorStand")
    floorStand:Hide()
  end
  hasDrain = false
  game.SubObject.Sleep(obj)
end
function OnPreStart(level, obj)
  curRuneNum = runeTable[currentState].num
  local frameTable = {
    enabled = 0,
    disabled = 60,
    dimEnabled = 60,
    dimDisabled = 60
  }
  for i = 1, totalRuneSlots do
    runeTable[i].runeVisual.LuaObjectScript.SetDimFrames(frameTable)
    runeTable[i].runeVisual.LuaObjectScript.SelectRune(runeTable[i].num)
  end
  if not hasDrain then
    DimRunes()
  end
end
function OnSaveCheckpoint(level, obj)
  return {previousState = currentState}
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  currentState = savedInfo.previousState
end
function SoftSave()
  game.SubObject.SoftSave(thisObj)
end
function ResolveSoftSave()
  thisObj:JumpAnimToFrame(runeTable[currentState].frame)
  thisObj:PauseAnim()
end
function PoweredStart()
  if not hasDrain then
    UndimRunes()
    local newState = currentState + 1
    hasDrain = true
    if 3 < newState then
      newState = 1
    end
    RotateClockwise(newState, poweredPlaySpeed)
  end
end
function PoweredEnd()
  hasDrain = false
  thisObj:ClearAllAnimCallbacks()
  local canSnapBack = false
  local previousState = currentState - 1
  if currentState == 1 then
    previousState = 3
    canSnapBack = thisObj.AnimFrame <= runeTable[currentState].snapBackframe
  else
    canSnapBack = thisObj.AnimFrame <= runeTable[currentState].snapBackframe and thisObj.AnimFrame < runeTable[currentState].frame
  end
  if canSnapBack then
    thisObj:PauseAnim()
    RotateCounterclockwise(previousState, poweredPlaySpeed)
  else
    ExecuteOnRotate()
  end
end
function RotateClockwise(newState, playRate)
  if currentState == 3 and newState == 1 then
    thisObj:PlayAnimToEnd(playRate)
  else
    thisObj:PlayAnimToFrame(runeTable[newState].frame, playRate)
  end
  thisObj:OnAnimDone(thisObj, "RotateClockwise_Powered")
  currentState = newState
  curRuneNum = runeTable[newState].num
  ExecuteOnRotate()
end
function RotateClockwise_Powered()
  timers.StartLevelTimer(poweredStopTime, function()
    if hasDrain then
      if thisObj.AnimFrame == thisObj.AnimLengthFrames then
        thisObj:JumpAnimToFrame(0)
      end
      if currentState + 1 > 3 then
        currentState = 0
      end
      RotateClockwise(currentState + 1, poweredPlaySpeed)
    end
  end)
end
function RotateCounterclockwise(newState, playRate)
  thisObj:PlayAnimToFrame(runeTable[newState].frame, -playRate)
  currentState = newState
  curRuneNum = runeTable[newState].num
  ExecuteOnRotate()
end
function GetCurrentRune()
  if hasDrain then
    return -1
  end
  return curRuneNum
end
function RegisterOnRotateCallback(fn)
  if fn ~= nil then
    table.insert(onRotate, fn)
  end
end
function ExecuteOnRotate()
  for i = 1, #onRotate do
    onRotate[i]()
  end
end
function DimRunes()
  for i = 1, 3 do
    runeTable[i].runeVisual.LuaObjectScript.Dim()
  end
end
function UndimRunes()
  for i = 1, 3 do
    runeTable[i].runeVisual.LuaObjectScript.Undim()
  end
end
function Debug_ToggleRunes()
  debug_runesOn = not debug_runesOn
  if debug_runesOn then
    for i = 1, 3 do
      runeTable[i].runeVisual.LuaObjectScript.Enable()
    end
  else
    for i = 1, 3 do
      runeTable[i].runeVisual.LuaObjectScript.Disable()
    end
  end
end
function Debug_ToggleDrain()
  if hasDrain then
    PoweredEnd()
  else
    PoweredStart()
  end
end
function ShowDebugText()
  local debugText = thisObj.Parent:GetName()
  debugText = debugText .. [[

 Current Frame ]] .. tostring(thisObj.AnimFrame)
  debugText = debugText .. [[

> Going to Frame ]] .. tostring(runeTable[currentState].frame)
  debugText = debugText .. [[

> Current-Future State ]] .. tostring(currentState)
  debugText = debugText .. [[

 HasDrain ]] .. tostring(hasDrain)
  engine.DrawTextInWorld(thisObj:GetWorldPosition(), debugText, color.white)
end
