var o = Object.defineProperty;
var d = (c, t, e) => t in c ? o(c, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[t] = e;
var s = (c, t, e) => d(c, typeof t != "symbol" ? t + "" : t, e);
import { useRefWithInit as f } from "./useRefWithInit.js";
import { useOnMount as m } from "./useOnMount.js";
const n = null;
let h = globalThis.requestAnimationFrame;
class I {
  constructor() {
    /* This implementation uses an array as a backing data-structure for frame callbacks.
     * It allows `O(1)` callback cancelling by inserting a `null` in the array, though it
     * never calls the native `cancelAnimationFrame` if there are no frames left. This can
     * be much more efficient if there is a call pattern that alterns as
     * "request-cancel-request-cancel-…".
     * But in the case of "request-request-…-cancel-cancel-…", it leaves the final animation
     * frame to run anyway. We turn that frame into a `O(1)` no-op via `callbacksCount`. */
    s(this, "callbacks", []);
    s(this, "callbacksCount", 0);
    s(this, "nextId", 1);
    s(this, "startId", 1);
    s(this, "isScheduled", !1);
    s(this, "tick", (t) => {
      var u;
      this.isScheduled = !1;
      const e = this.callbacks, r = this.callbacksCount;
      if (this.callbacks = [], this.callbacksCount = 0, this.startId = this.nextId, r > 0)
        for (let a = 0; a < e.length; a += 1)
          (u = e[a]) == null || u.call(e, t);
    });
  }
  request(t) {
    const e = this.nextId;
    this.nextId += 1, this.callbacks.push(t), this.callbacksCount += 1;
    const r = process.env.NODE_ENV === "test" && h !== requestAnimationFrame && (h = requestAnimationFrame, !0);
    return (!this.isScheduled || r) && (requestAnimationFrame(this.tick), this.isScheduled = !0), e;
  }
  cancel(t) {
    const e = t - this.startId;
    e < 0 || e >= this.callbacks.length || (this.callbacks[e] = null, this.callbacksCount -= 1);
  }
}
const i = new I();
class l {
  constructor() {
    s(this, "currentId", n);
    s(this, "cancel", () => {
      this.currentId !== n && (i.cancel(this.currentId), this.currentId = n);
    });
    s(this, "disposeEffect", () => this.cancel);
  }
  static create() {
    return new l();
  }
  static request(t) {
    return i.request(t);
  }
  static cancel(t) {
    return i.cancel(t);
  }
  /**
   * Executes `fn` after `delay`, clearing any previously scheduled call.
   */
  request(t) {
    this.cancel(), this.currentId = i.request(() => {
      this.currentId = n, t();
    });
  }
}
function A() {
  const c = f(l.create).current;
  return m(c.disposeEffect), c;
}
export {
  l as AnimationFrame,
  A as useAnimationFrame
};
