import { onScopeDispose as e, readonly as t, ref as n, shallowRef as r, toValue as i, watch as a } from "vue";
var o = /* @__PURE__ */ function(e) {
	return e.Normal = "normal", e.External = "external", e;
}(o || {});
function s(e) {
	return e instanceof Error ? e : Error(typeof e == "string" ? e : JSON.stringify(e));
}
/**
* Repeatedly executes an asynchronous query while tracking arguments, state transitions,
* and result freshness.
*
* @remarks
*
* ### Typical usage
*
* ```ts
* const args = ref({ id: 'item-1' });
* const { data, pause, resume, lastError } = usePollingQuery(args, fetchItem, {
*   minInterval: 5_000,
*   minDelay: 250,
* });
* ```
*
* The composable polls `fetchItem` while `resume()`d. Whenever the `args` ref changes the current
* request is aborted, the status becomes `'stale'`, and a new poll is scheduled after the optional
* debounce period and the configured timing constraints. Results from older requests are ignored
* through version tracking, ensuring consumers only observe the freshest payload.
*
* ### Timing behaviour
*
* - `minInterval` defines the minimum duration between the start times of consecutive polls.
* - `minDelay` (optional) enforces a minimum wait time between a poll finishing and the next poll starting.
* - After each poll completes, the next poll is scheduled `max(minInterval - elapsed, minDelay)` ms later.
* - When arguments change, the next poll still respects both constraints while also honouring the debounce.
*
* ### Abort handling
*
* Each poll receives a dedicated `AbortSignal`. The signal is aborted when pausing, disposing
* the scope, or when the arguments ref changes. Queries should surface aborts by listening to
* the signal. Aborted requests may settle later; outdated results are discarded via version checks.
*
* ### Pause, resume, and callback control
*
* - `pause()` stops future polls, clears pending timeouts, and aborts in-flight requests.
* - `resume()` is idempotent; it reactivates polling only when currently inactive.
* - The callback receives a bound `pause()` helper for conditional pausing.
*
* ### Error handling
*
* Errors bubble into `lastError`; they reset on the next successful poll or when `resume()`
* transitions from inactive to active. With `pauseOnError: true` the composable pauses automatically.
*
* ### Argument tracking
*
* - Initial state is `{ status: 'idle' }`.
* - Argument changes mark the status `'stale'` when a prior result exists; otherwise it stays `'idle'`.
* - A successful poll for the latest arguments marks the status `'synced'` and updates `value`.
*
* ### Request versioning and concurrency
*
* Each poll increments an internal version counter. Only the latest version updates shared state,
* preventing stale results from overwriting fresh data. `maxInFlightRequests` limits concurrent
* polls; values > 1 allow the next poll to begin even if aborted requests are still settling, while
* still capping total concurrency to protect upstream services.
*
* ### Debouncing
*
* Use `debounce` to accumulate rapid argument changes. The status still transitions to `'stale'`
* immediately, all running polls are aborted, and the new poll waits for the debounce window
* (and the timing constraints) before executing.
*
* ### Options
*
* - `minInterval` — required; must be positive. Zero or negative disables polling (`resume()` no-op). Accepts refs.
* - `minDelay` — optional delay after completion before the next poll may start. Accepts refs.
* - `autoStart` — start in active mode (default `true`).
* - `triggerOnResume` — run the callback immediately on `resume()` (default `false`).
* - `pauseOnError` — automatically pauses when the callback throws (default `false`).
* - `maxInFlightRequests` — maximum concurrent polls (default `1`).
* - `debounce` — debounce window for argument changes in milliseconds (default `0`).
*
* ### Returns
*
* - `data` — readonly ref of `{ status, value }`.
* - `lastError` — readonly ref of the latest error (or `null`).
* - `isActive` — readonly ref indicating active polling.
* - `inFlightCount` — readonly ref with the number of active requests.
* - `pause()` and `resume()` controls.
*
* @typeParam Args - Arguments shape passed to the polling callback.
* @typeParam Result - Result type produced by the polling callback.
*/
function c(c, l, u) {
	let d = {
		minInterval: u.minInterval,
		minDelay: u.minDelay ?? 0,
		autoStart: u.autoStart ?? !0,
		triggerOnResume: u.triggerOnResume ?? !1,
		pauseOnError: u.pauseOnError ?? !1,
		maxInFlightRequests: Math.max(1, u.maxInFlightRequests ?? 1),
		debounce: Math.max(0, u.debounce ?? 0)
	}, f = () => Math.max(0, i(d.minInterval)), p = () => {
		let e = d.minDelay === void 0 ? void 0 : i(d.minDelay);
		return Math.max(0, e ?? 0);
	}, m = () => f() > 0, h = r({ status: "idle" }), g = n(null), _ = n(!1), v = 0, y = 0, b = n(0), x = !1, S = null, C = null, w = 0, T = 0, E = /* @__PURE__ */ new Map(), D = /* @__PURE__ */ new Map(), O = [], k, A = !1, j = (e) => {
		k = e, A = !0;
	}, M = () => {
		if (h.value.status === "synced" || h.value.status === "stale") {
			let { value: e } = h.value;
			h.value = {
				status: "stale",
				value: e
			};
		}
	}, N = () => {
		O.length !== 0 && O.shift()?.resolve();
	}, P = async () => {
		b.value < d.maxInFlightRequests || await new Promise((e) => {
			O.push({ resolve: e });
		});
	}, F = () => {
		S !== null && (clearTimeout(S), S = null);
	}, I = () => {
		C !== null && (clearTimeout(C), C = null);
	}, L = (e) => {
		E.forEach((t, n) => {
			t.signal.aborted || (D.set(n, e), t.abort());
		});
	}, R = (e = 0) => {
		let t = Date.now(), n = Math.max(w, T), r = n > t ? n - t : 0;
		return Math.max(0, e, r);
	}, z = (e = 0, t = o.Normal) => {
		if (!_.value || !m() || x) return;
		let n = R(e);
		S !== null && clearTimeout(S), S = setTimeout(() => {
			S = null, B(t);
		}, n);
	}, B = async (e) => {
		if (!_.value || x || !m()) return;
		let t = Date.now(), n = Math.max(w, T);
		if (t < n) {
			z(n - t, e);
			return;
		}
		if (!A) return;
		let r = k, i = y;
		if (await P(), !_.value || x || !m()) {
			N();
			return;
		}
		let a = new AbortController(), o = ++v;
		E.set(o, a), b.value += 1;
		let c = f(), u = Date.now();
		w = Math.max(w, u + c);
		let S = !1, C = () => {
			S || (S = !0, U());
		};
		try {
			let e = await l(r, {
				signal: a.signal,
				pause: C
			});
			a.signal.aborted || o === v && i === y && (g.value = null, h.value = {
				status: "synced",
				value: e
			});
		} catch (e) {
			a.signal.aborted || (o === v && (g.value = s(e)), d.pauseOnError && U());
		} finally {
			let e = p(), t = Date.now();
			T = Math.max(T, t + e), E.delete(o), b.value = Math.max(0, b.value - 1), N();
			let n = D.get(o);
			n && D.delete(o), _.value && !x && n !== "args" && z();
		}
	}, V = (e = o.External) => {
		!_.value || x || !m() || z(0, e);
	}, H = () => {
		if (y += 1, M(), L("args"), !_.value || !m()) return;
		let e = () => {
			V(o.External);
		};
		d.debounce > 0 ? (I(), C = setTimeout(() => {
			C = null, e();
		}, d.debounce)) : e();
	}, U = () => {
		_.value && (_.value = !1, F(), I(), L("pause"), w = Date.now(), T = Date.now());
	}, W = () => {
		if (!m() || _.value || !A) return;
		_.value = !0, g.value = null;
		let e = Date.now();
		w = e, T = e, d.triggerOnResume ? V(o.External) : z(f(), o.External);
	};
	return e(() => {
		x = !0, F(), I(), L("dispose"), _.value = !1, O.splice(0, O.length).forEach(({ resolve: e }) => e());
	}), a(c, (e) => {
		let t = !A;
		j(e), !t && H();
	}, {
		flush: "sync",
		immediate: !0
	}), d.autoStart && m() && W(), {
		data: t(h),
		lastError: t(g),
		isActive: t(_),
		inFlightCount: t(b),
		pause: U,
		resume: W
	};
}
export { c as usePollingQuery };

//# sourceMappingURL=usePollingQuery.js.map