var frame = 0, timeout = 0, interval = 0, pokeDelay = 1e3, taskHead, taskTail, clockLast = 0, clockNow = 0, clockSkew = 0, clock = typeof performance == "object" && performance.now ? performance : Date, setFrame = typeof window == "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(e) {
	setTimeout(e, 17);
};
function now() {
	return clockNow ||= (setFrame(clearNow), clock.now() + clockSkew);
}
function clearNow() {
	clockNow = 0;
}
function Timer() {
	this._call = this._time = this._next = null;
}
Timer.prototype = timer.prototype = {
	constructor: Timer,
	restart: function(e, g, _) {
		if (typeof e != "function") throw TypeError("callback is not a function");
		_ = (_ == null ? now() : +_) + (g == null ? 0 : +g), !this._next && taskTail !== this && (taskTail ? taskTail._next = this : taskHead = this, taskTail = this), this._call = e, this._time = _, sleep();
	},
	stop: function() {
		this._call && (this._call = null, this._time = Infinity, sleep());
	}
};
function timer(e, g, _) {
	var v = new Timer();
	return v.restart(e, g, _), v;
}
function timerFlush() {
	now(), ++frame;
	for (var g = taskHead, _; g;) (_ = clockNow - g._time) >= 0 && g._call.call(void 0, _), g = g._next;
	--frame;
}
function wake() {
	clockNow = (clockLast = clock.now()) + clockSkew, frame = timeout = 0;
	try {
		timerFlush();
	} finally {
		frame = 0, nap(), clockNow = 0;
	}
}
function poke() {
	var e = clock.now(), g = e - clockLast;
	g > pokeDelay && (clockSkew -= g, clockLast = e);
}
function nap() {
	for (var e, g = taskHead, _, v = Infinity; g;) g._call ? (v > g._time && (v = g._time), e = g, g = g._next) : (_ = g._next, g._next = null, g = e ? e._next = _ : taskHead = _);
	taskTail = e, sleep(v);
}
function sleep(y) {
	frame || (timeout &&= clearTimeout(timeout), y - clockNow > 24 ? (y < Infinity && (timeout = setTimeout(wake, y - clock.now() - clockSkew)), interval &&= clearInterval(interval)) : (interval ||= (clockLast = clock.now(), setInterval(poke, pokeDelay)), frame = 1, setFrame(wake)));
}
export { Timer, now, timer, timerFlush };
