// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

/** Options for {@linkcode delay}. */
export interface DelayOptions {
  /** Signal used to abort the delay. */
  signal?: AbortSignal;
  /** Indicates whether the process should continue to run as long as the timer exists.
   *
   * @default {true}
   */
  persistent?: boolean;
}

/**
 * Resolve a {@linkcode Promise} after a given amount of milliseconds.
 *
 * @throws {DOMException} If the optional signal is aborted before the delay
 * duration, and `signal.reason` is undefined.
 * @param ms Duration in milliseconds for how long the delay should last.
 * @param options Additional options.
 *
 * @example Basic usage
 * ```ts no-assert
 * import { delay } from "@std/async/delay";
 *
 * // ...
 * const delayedPromise = delay(100);
 * const result = await delayedPromise;
 * // ...
 * ```
 *
 * @example Disable persistence
 *
 * Setting `persistent` to `false` will allow the process to continue to run as
 * long as the timer exists.
 *
 * ```ts no-assert
 * import { delay } from "@std/async/delay";
 *
 * // ...
 * await delay(100, { persistent: false });
 * // ...
 * ```
 */
export function delay(ms: number, options: DelayOptions = {}): Promise<void> {
  const { signal, persistent = true } = options;
  if (signal?.aborted) return Promise.reject(signal.reason);
  return new Promise((resolve, reject) => {
    const abort = () => {
      clearTimeout(i);
      reject(signal?.reason);
    };
    const done = () => {
      signal?.removeEventListener("abort", abort);
      resolve();
    };
    const i = setTimeout(done, ms);
    signal?.addEventListener("abort", abort, { once: true });
    if (persistent === false) {
      try {
        // @ts-ignore For browser compatibility
        Deno.unrefTimer(i);
      } catch (error) {
        if (!(error instanceof ReferenceError)) {
          throw error;
        }
        console.error("`persistent` option is only available in Deno");
      }
    }
  });
}

// denoCacheMetadata={"headers":{"content-length":"2039","x-jsr-backend":"modules","cache-control":"public, max-age=31536000, immutable","vary":"Origin","age":"545107","access-control-expose-headers":"*","etag":"\"29e8aaaccd034d3a404f869151336242\"","x-robots-tag":"noindex","set-cookie":"__cf_bm=VJx_MAs8seqm3Lrjel5vE.qdE4YO_fQf.hzcXhSTeSE-1785241875.3125644-1.0.1.1-h4rotwvlFQiDeXfqVlrt6BMvXnuZm1lqSyNMSaWCrIMxWGwVDvivHooXO92zQCAo3itM5fHWk.k3Ryoz_kj1eVZvEqRUYO3O9GsgB9qtp7QusrtQwCkzLiLEfZQ0axOB; HttpOnly; SameSite=None; Secure; Path=/; Domain=jsr.io; Expires=Tue, 28 Jul 2026 13:01:15 GMT","content-type":"text/typescript","cf-cache-status":"HIT","alt-svc":"h3=\":443\"; ma=86400","cross-origin-resource-policy":"cross-origin","date":"Tue, 28 Jul 2026 12:31:15 GMT","x-content-type-options":"nosniff","access-control-allow-origin":"*","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"https://a.nel.cloudflare.com/report/v4?s=ubcY1T8egSJkz4bxtdCcB76GE1m00Eea1588H5sCIveX2yg02Nmz6mJZbVVKvj4TLkWzMPw%2BjaVxlxvrgUP9vUVJe66SvAMSWuXCPN4emAjWPMnkqNEs5%2FE%3D\"}]}","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","server":"cloudflare","cf-ray":"a223e658bd377db6-LAX","accept-ranges":"bytes","content-security-policy":"default-src 'none'; script-src 'none'; style-src 'none'; img-src 'none'; font-src 'none'; connect-src 'none'; frame-src 'none'; object-src 'none'; frame-ancestors 'none'; sandbox; form-action 'none';"},"url":"https://jsr.io/@std/async/1.0.5/delay.ts","time":1785241875}