local classlib = require("core.class")
local runlist = require("core.runlist")
local timer = require("core.timer")
local statelib = require("ai.state")
local statelogic = require("ai.statelogic")
local AttachedTimer = function(period, callback, ...)
  local CS = statelogic.call_state()
  local M, state = CS.M, CS.executing_state
  local SI = statelogic.get_state_instance(M, state.Name)
  local transient = SI.transient
  local RL = transient.AttachedTimers or runlist.RunList.New()
  transient.AttachedTimers = RL
  local T = timer.Timer.New(RL, period, callback, ...)
  T:Start()
  return T
end
local get_global_timers = function(M)
  local GI = statelogic.get_global_instance(M)
  local RL = GI.GlobalTimers or runlist.RunList.New()
  GI.GlobalTimers = RL
  return RL
end
local GlobalTimer = function(period, callback, ...)
  local CS = statelogic.call_state()
  local M = CS.M
  local RL = get_global_timers(M)
  local T = timer.Timer.New(RL, period, callback, ...)
  T:Start()
  return T
end
local UpdateTimers = function(M, dt, ...)
  local CS = statelogic.call_start(M, nil, nil, ...)
  local GI = statelogic.get_global_instance(M)
  local GlobalTimers = GI.GlobalTimers
  if GlobalTimers then
    GlobalTimers:Update(dt)
  end
  for _, S in pairs(M.States) do
    local SI = statelogic.get_state_instance(M, S.Name)
    local transient = SI.transient
    local AttachedTimers = transient.AttachedTimers
    if AttachedTimers then
      AttachedTimers:Update(dt)
    end
  end
  statelogic.call_end(CS)
end
local TimerState = classlib.Class("TimerState", statelib.State)
function TimerState:state_init()
  local callState = statelogic.call_state()
  local M = callState.M
  local SI = statelogic.get_state_instance(M, self.Name)
  local RL = get_global_timers(M)
  for _, group in pairs({"Events", "Hooks"}) do
    for k, fn in pairs(self[group]) do
      local dispatchFn = function(self, ...)
        return fn(self, SI.TimerInstance, ...)
      end
      classlib.register_profile_marker(dispatchFn, self.CLASS.LEAFNAME, group, k)
      self[group][k] = dispatchFn
    end
  end
  local timerstate_callback = function()
    local CS = statelogic.call_state()
    local onTimerComplete = self.OnTimerComplete
    if onTimerComplete then
      onTimerComplete(self, SI.TimerInstance, unpack(CS.args))
    end
  end
  local T = timer.Timer.New(RL, nil, timerstate_callback)
  T.fromTimerState = true
  SI.TimerInstance = T
  classlib.initializer(T, self.CLASS)
  assert(T.period, "No period set on timer!")
  if T.autostart then
    T:Start()
  end
end
function TimerState:GetTimer()
  local callState = statelogic.call_state()
  local M = callState.M
  local SI = statelogic.get_state_instance(M, self.Name)
  return SI.TimerInstance
end
return {
  TimerState = TimerState,
  AttachedTimer = AttachedTimer,
  GlobalTimer = GlobalTimer,
  UpdateTimers = UpdateTimers
}
