-- Timer (not mine lol) (i genuinely forget who i stole the original code from
-- so even if i knew there's nothing i could do)
-- TODO investigate if events can replace some of this
timers={}
do
	local timers = {}
	--- Wait
	--Wait a certain number of ticks and execute a function.
	---@param ticks integer Number of ticks to wait
	---@param next function Callback to run
	function wait(ticks,next)
		table.insert(timers, {t=world.getTime()+ticks,n=next})
	end
	local function tick()
		for key,timer in pairs(timers) do
			if world.getTime() >= timer.t then
				timer.n()
				table.remove(timers,key)
			end
		end
	end

	events.TICK:register(function() if player then tick() end end, "timer")
end
timers.wait=wait

-- named timers (this one is mine but heavily based on the other) --
-- if timer is armed twice before expiring it will only be called once) --
do
	local timers = {}
	--- Wait
	--Wait a certain number of ticks and execute a function. Store the timer with a name so that
	--it can be overwritten.
	---@param ticks integer Number of ticks to wait
	---@param next function Callback to run
	---@param name function Name of callback
	function namedWait(ticks, next, name)
		-- main difference, this will overwrite an existing timer with
		-- the same name
		timers[name]={t=world.getTime()+ticks,n=next}
	end
	local function tick()
		for key, timer in pairs(timers) do
			if world.getTime() >= timer.t then
				timer.n()
				timers[key]=nil
			end
		end
	end
	events.TICK:register(function() if player then tick() end end, "named_timer")
end
timers.namedWait=namedWait

-- named cooldowns
do
	local timers={}
	function cooldown(ticks, name)
		if timers[name] == nil then
			timers[name]={t=world.getTime()+ticks}
			return true
		end
		return false
	end
	local function tick()
		for key, timer in pairs(timers) do
			if world.getTime() >= timer.t then
				timers[key]=nil
			end
		end
	end
	events.TICK:register(function() if player then tick() end end, "cooldown")
end

function rateLimit(ticks, next, name)
	if timers.cooldown(ticks+1, name) then
		timers.namedWait(ticks, next, name)
	end
end

timers.rateLimit=rateLimit

return timers