/// <reference lib="es2018" />
/**
 * Calls the provided `callbackFn` function once for each element in an array (or ArratLike) instance in ascending index order. It is not invoked
 * for index properties that have been deleted or are uninitialized. And unlike the ES6 forEach() this supports async functions and you CAN stop
 * or break the iteration  by returning -1 from the `callbackFn` function.
 *
 * The range (number of elements) processed by arrForEach() is set before the first call to the `callbackFn`. Any elements added beyond the range
 * or elements which as assigned to indexes already processed will not be visited by the `callbackFn`.
 *
 * The `callbackFn` may execute `synchronously` or `asynchronously` and if the `callbackFn` returns a `Promise` then the next iteration will not be
 * called until the promise is resolved. If the `callbackFn` returns a `Promise` that is rejected then the iteration will stop and the promise
 * returned by arrForEachAsync will be rejected with the same error.
 * @since 0.5.0
 * @group Loop
 * @group Array
 * @group ArrayLike
 * @typeParam T - Identifies the element type of the array
 * @param theArray - The array or array like object of elements to be searched.
 * @param callbackFn - A `asynchronous` or `synchronous` function that accepts up to three arguments. arrForEach calls the callbackfn function one
 * time for each element in the array.
 * @param thisArg - An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, null or undefined
 * the array will be used as the this value.
 * @remarks
 * arrForEachAsync supports either a `synchronous` or `asynchronous` (returns a `Promise`) callback function. If the callback function returns
 * a `Promise` then the next iteration will not be called until the promise is resolved. If the callback function returns a `Promise` that is
 * rejected then the iteration will stop and the promise returned by arrForEachAsync will be rejected with the same error.
 * @example
 * ```ts
 * const items = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7', 'item8', 'item9', 'item10'];
 * const copyItems = [];
 *
 * arrForEachASync(items, (value, index) => {
 *   copyItems.push(value);
 *   if (index === 5) {
 *     return -1; // Stop the iteration
 *   }
 * });
 * console.log(copyItems); // ['item1', 'item2', 'item3', 'item4', item5']
 *
 * // Also supports input as an array like object
 * const items = { length: 3, 0: 'item1', 1: 'item2', 2: 'item3' };
 *
 * // Asynchronous examples using await
 * const items = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7', 'item8', 'item9', 'item10'];
 * const copyItems = [];
 *
 * await arrForEachASync(items, (value, index) => { // Note: DO NOT use async here unless you use await within the function
 *   if (index < 5) {
 *     // Logs each iteration index
 *     // Logs each value
 *     console.log(value);
 *     // Returning a promise will cause `arrForEachAsync` to return a promise to the caller
 *     // and wait for the promise to resolve before calling the callback function again.
 *     return createTimeoutPromise(10, true);
 *   }
 *
 *   return -1; // Stop the iteration
 * });
 * console.log(copyItems); // ['item1', 'item2', 'item3', 'item4', item5']
 *
 * ```
 */
export declare function arrForEachAsync<T = any>(theArray: ArrayLike<T>, callbackFn: (value: T, index: number, array: T[]) => void | number | IPromise<void | number>, thisArg?: any): void | number | IPromise<void | number>;

/**
 * A Simple type which identifies the result of a promise as a single response, it identifies
 * if the promise was rejected or resolved along with the resolved value or rejected reason.
 * It is a union of the `IPromiseFulfilledResult` and `IPromiseRejectedResult` interfaces the
 * response will contain the `rejected` property which will be true if the promise was rejected
 * or false if the promise was resolved. The `status` property will be set to either "fulfilled"
 * or "rejected" to identify the status of the promise. The `value` or `reason` properties will
 * contain the resolved value or rejected reason respectively.
 *
 * @group Promise
 * @typeParam T - The type of the fulfilled value.
 *
 * @example
 * ```ts
 * const result: AwaitResponse<number> = {
 *   status: "fulfilled",
 *   value: 42
 * };
 *
 * const result: AwaitResponse<number> = {
 *   rejected: true,
 *   status: "rejected",
 *   reason: "Hello Darkness"
 * };
 * ```
 */
export declare interface AwaitResponse<T, R = any> {
    /**
     * A string indicating that the promise was rejected.
     */
    status: "fulfilled" | "rejected";
    /**
     * The value that the promise was fulfilled with.
     */
    value?: T;
    /**
     * The reason that the promise was rejected with.
     */
    reason?: R;
    /**
     * Identifies if the promise was rejected (true) or was resolved (false/undefined)
     */
    rejected?: boolean;
}

/**
 * Returns a single asynchronous Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations __asynchronously__ using the optional
 * provided timeout value to schedule when the chained items will be executed, or if the input contains no promises.
 * It rejects immediately upon any of the input promises rejected or non-promises throwing an error,
 * and will reject with this first rejection message / error.
 * If the runtime doesn't support the Promise.all it will fallback back to an asynchronous Promise implementation.
 *
 * @function
 * @group Alias
 * @group Promise
 * @group All
 * @param input - The array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 * @returns
 * <ul>
 * <li> An already resolved `Promise`, if the input passed is empty.
 * <li> A pending `Promise` in all other cases. This returned promise is then resolved/rejected __synchronously__
 * (as soon as the pending items is empty) when all the promises in the given input have resolved, or if any of the
 * promises reject.
 * </ul>
 */
export declare const createAllPromise: <T>(input: Iterable<PromiseLike<T>>, timeout?: number) => IPromise<T[]>;

/**
 * Returns a single Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations based on the current
 * promise implementation. If the current implementation is synchronous then the chained operations will
 * execute __synchronously__ in the same execution cycle as the final operation pending promises have resolved,
 * or if the input contains no promises. If the current implementation is asynchronous then the chained
 * operations will execute __asynchronously__ using the optional provided timeout value to schedule when the
 * chained items will be executed or if the input contains no promises.
 * It will resolve only after all of the input promises have either resolved or rejected, and will resolve with an array
 * of {@link IPromiseResult } objects that each describe the outcome of each promise.
 * @since 0.5.0
 * @group Alias
 * @group Promise
 * @group AllSettled
 * @param values - The iterator of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A pending `Promise` that will resolve to an array of {@link IPromiseResult } objects that each describe the outcome of each promise.
 *
 * @example
 * ```ts
 * const promises = [
 *   createResolvedPromise(1),
 *   createResolvedPromise(2),
 *   createResolvedPromise(3),
 *   createRejectedPromise("error"),
 * ];
 *
 * const results = await createAllSettledPromise(promises);
 *
 * // results is:
 * // [
 * //   { status: "fulfilled", value: 1 },
 * //   { status: "fulfilled", value: 2 },
 * //   { status: "fulfilled", value: 3 },
 * //   { status: "rejected", reason: "error" }
 * // ]
 * ```
 */
export declare function createAllSettledPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<IPromiseResult<Awaited<T>>[]>;

/**
 * The `createAnyPromise` method takes an iterable of promises as input and returns a single Promise.
 * This returned promise fulfills when any of the input's promises fulfills, with this first fulfillment value.
 * It rejects when all of the input's promises reject (including when an empty iterable is passed), with an
 * AggregateError containing an array of rejection reasons.
 * @since 0.5.0
 * @group Alias
 * @group Promise
 * @group Any
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A new Promise that is:
 * - Already rejected, if the iterable passed is empty.
 * - Asynchronously fulfilled, when any of the promises in the given iterable fulfills. The fulfillment value
 * is the fulfillment value of the first promise that was fulfilled.
 * - Asynchronously rejected, when all of the promises in the given iterable reject. The rejection reason is
 * an AggregateError containing an array of rejection reasons in its errors property. The errors are in the
 * order of the promises passed, regardless of completion order. If the iterable passed is non-empty but
 * contains no pending promises, the returned promise is still asynchronously (instead of synchronously)
 * rejected.
 */
export declare function createAnyPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Returns a single asynchronous Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations __asynchronously__ using the optional
 * provided timeout value to schedule when the chained items will be executed, or if the input contains no promises.
 * It rejects immediately upon any of the input promises rejected or non-promises throwing an error,
 * and will reject with this first rejection message / error.
 * When resolved or rejected any additional chained operations will execute __asynchronously__ using the optional
 * timeout value to schedul when the chained item will be executed (eg. `then()`; `catch()`; `finally()`).
 *
 * @function
 * @group Async
 * @group Promise
 * @group All
 * @param input - The array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 * @returns
 * <ul>
 * <li> An already resolved `Promise`, if the input passed is empty.
 * <li> A pending `Promise` in all other cases. This returned promise is then resolved/rejected __synchronously__
 * (as soon as the pending items is empty) when all the promises in the given input have resolved, or if any of the
 * promises reject.
 * </ul>
 */
export declare const createAsyncAllPromise: <T>(input: Iterable<PromiseLike<T>>, timeout?: number) => IPromise<T[]>;

/**
 * Returns a single Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations based on the
 * {@link createAsyncPromise | Asynchronous} promise implementation. Any chained operations will execute
 * __asynchronously__  when the final operation pending promises have resolved, or if the input contains
 * no promises. It will resolve only after all of the input promises have either resolved or rejected,
 * and will resolve with an array of {@link IPromiseResult } objects that each describe the outcome of
 * each promise.
 * @since 0.5.0
 * @group Async
 * @group Promise
 * @group AllSettled
 * @param values - The iterator of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A pending `Promise` that will resolve to an array of {@link IPromiseResult } objects that each describe the outcome of each promise.
 *
 * @example
 * ```ts
 * const promises = [
 *   createResolvedPromise(1),
 *   createResolvedPromise(2),
 *   createResolvedPromise(3),
 *   createRejectedPromise("error"),
 * ];
 *
 * const results = await createAllSettledPromise(promises);
 *
 * // results is:
 * // [
 * //   { status: "fulfilled", value: 1 },
 * //   { status: "fulfilled", value: 2 },
 * //   { status: "fulfilled", value: 3 },
 * //   { status: "rejected", reason: "error" }
 * // ]
 * ```
 */
export declare function createAsyncAllSettledPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<IPromiseResult<Awaited<T>>[]>;

/**
 * The `createAsyncAnyPromise` method takes an iterable of promises as input and returns a single Promise.
 * This returned promise fulfills when any of the input's promises fulfills, with this first fulfillment value.
 * It rejects when all of the input's promises reject (including when an empty iterable is passed), with an
 * AggregateError containing an array of rejection reasons.
 * @since 0.5.0
 * @group Async
 * @group Promise
 * @group Any
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A new Promise that is:
 * - Already rejected, if the iterable passed is empty.
 * - Asynchronously fulfilled, when any of the promises in the given iterable fulfills. The fulfillment value
 * is the fulfillment value of the first promise that was fulfilled.
 * - Asynchronously rejected, when all of the promises in the given iterable reject. The rejection reason is
 * an AggregateError containing an array of rejection reasons in its errors property. The errors are in the
 * order of the promises passed, regardless of completion order. If the iterable passed is non-empty but
 * contains no pending promises, the returned promise is still asynchronously (instead of synchronously)
 * rejected.
 */
export declare function createAsyncAnyPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Creates an asynchronous Promise instance that when resolved or rejected will execute it's pending chained operations
 * __asynchronously__ using the optional provided timeout value to schedule when the chained items will be ececuted.
 * @group Async
 * @group Promise
 * @param executor - The function to be executed during the creation of the promise. Any errors thrown in the executor will
 * cause the promise to be rejected. The return value of the executor is always ignored
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare function createAsyncPromise<T>(executor: PromiseExecutor<T>, timeout?: number): IPromise<T>;

/**
 * The `createAsyncRacePromise` method takes an array of promises as input and returns a single Promise. This returned promise
 * settles with the eventual state of the first promise that settles.
 * @description The `createAsyncRacePromise` method is one of the promise concurrency methods. It's useful when you want the first
 * async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
 * If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race() will settle to
 * the first of these values found in the iterable.
 * @since 0.5.0
 * @group Async
 * @group Promise
 * @group Race
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A Promise that settles with the eventual state of the first promise in the iterable to settle. In other words, it fulfills if the
 * first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever
 * if the iterable passed is empty. If the iterable passed is non-empty but contains no pending promises, the returned promise is still
 * asynchronously settled.
 */
export declare function createAsyncRacePromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Returns a single asynchronous Promise instance that is already rejected with the given reason.
 * Any chained operations will execute __asynchronously__ using the optional timeout value to schedule
 * when then chained items will be executed. (eg. `catch()`; `finally()`).
 *
 * @function
 * @group Async
 * @group Promise
 * @group Rejected
 * @param reason - The rejection reason
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createAsyncRejectedPromise: <T = unknown>(reason: any, timeout?: number) => IPromise<T>;

/**
 * Returns a single asynchronous Promise instance that is already resolved with the given value. If the value passed is
 * a promise then that promise is returned instead of creating a new asynchronous promise instance.
 * If a new instance is returned then any chained operations will execute __asynchronously__ using the optional
 * timeout value to schedule when the chained items will be executed.(eg. `then()`; `finally()`).
 *
 * @function
 * @group Async
 * @group Promise
 * @group Resolved
 * @param value - The value to be used by this `Promise`. Can also be a `Promise` or a thenable to resolve.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createAsyncResolvedPromise: <T>(value: T, timeout?: number) => IPromise<T>;

/**
 * Returns an idle Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations __asynchronously__
 * using the `requestIdleCallback` API (if available) with the optional provided timeout value to
 * schedule when the chained items will be executed.
 * It rejects immediately upon any of the input promises rejected or non-promises throwing an error,
 * and will reject with this first rejection message / error.
 * When resolved or rejected any additional chained operations will execute __asynchronously__ using
 * the `requestIdleCallback` API (if available) with the optional provided timeout value to schedule
 * when the chained items will be executed. (eg. `then()`; `catch()`; `finally()`).
 *
 * @function
 * @group Idle
 * @group Promise
 * @group All
 * @param input - The array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional deadline timeout to wait before processing the items, defaults to undefined. If the number of
 * milliseconds represented by this parameter has elapsed and the callback has not already been called, then a task to execute
 * the callback is queued in the event loop (even if doing so risks causing a negative performance impact). timeout must be a
 * positive value or it is ignored.
 * @returns
 * <ul>
 * <li> An already resolved `Promise`, if the input passed is empty.
 * <li> A pending `Promise` in all other cases. This returned promise is then resolved/rejected __synchronously__
 * (as soon as the pending items is empty) when all the promises in the given input have resolved, or if any of the
 * promises reject.
 * </ul>
 */
export declare const createIdleAllPromise: <T>(input: Iterable<PromiseLike<T>>, timeout?: number) => IPromise<T[]>;

/**
 * Returns a single Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations based on the
 * {@link createIdlePromise | idle} promise implementation. Any chained operations will execute
 * __asynchronously__ when the environment is idle as the final operation pending promises have resolved,
 * or if the input contains no promises. It will resolve only after all of the input promises have either
 * resolved or rejected, and will resolve with an array of {@link IPromiseResult } objects that each describe
 * the outcome of each promise.
 * @since 0.5.0
 * @group Idle
 * @group Promise
 * @group AllSettled
 * @param values - The iterator of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A pending `Promise` that will resolve to an array of {@link IPromiseResult } objects that each describe the outcome of each promise.
 *
 * @example
 * ```ts
 * const promises = [
 *   createResolvedPromise(1),
 *   createResolvedPromise(2),
 *   createResolvedPromise(3),
 *   createRejectedPromise("error"),
 * ];
 *
 * const results = await createAllSettledPromise(promises);
 *
 * // results is:
 * // [
 * //   { status: "fulfilled", value: 1 },
 * //   { status: "fulfilled", value: 2 },
 * //   { status: "fulfilled", value: 3 },
 * //   { status: "rejected", reason: "error" }
 * // ]
 * ```
 */
export declare function createIdleAllSettledPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<IPromiseResult<Awaited<T>>[]>;

/**
 * The `createIdleAnyPromise` method takes an iterable of promises as input and returns a single Promise.
 * This returned promise fulfills when any of the input's promises fulfills, with this first fulfillment value.
 * It rejects when all of the input's promises reject (including when an empty iterable is passed), with an
 * AggregateError containing an array of rejection reasons.
 * @since 0.5.0
 * @group Idle
 * @group Promise
 * @group Any
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A new Promise that is:
 * - Already rejected, if the iterable passed is empty.
 * - Asynchronously fulfilled, when any of the promises in the given iterable fulfills. The fulfillment value
 * is the fulfillment value of the first promise that was fulfilled.
 * - Asynchronously rejected, when all of the promises in the given iterable reject. The rejection reason is
 * an AggregateError containing an array of rejection reasons in its errors property. The errors are in the
 * order of the promises passed, regardless of completion order. If the iterable passed is non-empty but
 * contains no pending promises, the returned promise is still asynchronously (instead of synchronously)
 * rejected.
 */
export declare function createIdleAnyPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Creates an idle Promise instance that when resolved or rejected will execute it's pending chained operations
 * __asynchronously__ using the `requestIdleCallback` API (if available) with the optional provided timeout value to
 * schedule when the chained items will be executed. When `requestIdleCallback` is not available this becomes the same as
 * `createAsyncPromise` which uses `setTimeout` to schedule executions.
 * @group Idle
 * @group Promise
 * @param executor - The function to be executed during the creation of the promise. Any errors thrown in the executor will
 * cause the promise to be rejected. The return value of the executor is always ignored
 * @param timeout - Optional deadline timeout to wait before processing the items, defaults to undefined. If the number of
 * milliseconds represented by this parameter has elapsed and the callback has not already been called, then a task to execute
 * the callback is queued in the event loop (even if doing so risks causing a negative performance impact). timeout must be a
 * positive value or it is ignored.
 */
export declare function createIdlePromise<T>(executor: PromiseExecutor<T>, timeout?: number): IPromise<T>;

/**
 * The `createIdleRacePromise` method takes an array of promises as input and returns a single Promise. This returned promise
 * settles with the eventual state of the first promise that settles.
 * @description The `createIdleRacePromise` method is one of the promise concurrency methods. It's useful when you want the first
 * async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
 * If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race() will settle to
 * the first of these values found in the iterable.
 * @since 0.5.0
 * @group Idle
 * @group Promise
 * @group Race
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A Promise that settles with the eventual state of the first promise in the iterable to settle. In other words, it fulfills if the
 * first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever
 * if the iterable passed is empty. If the iterable passed is non-empty but contains no pending promises, the returned promise will settle
 * asynchronously when the system detects that the runtime is idle.
 */
export declare function createIdleRacePromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Returns an idle Promise instance that is already rejected with the given reason.
 * Any chained operations will execute __asynchronously__ using the o`requestIdleCallback` API
 * (if available) with the optional provided timeout value to schedule when the chained items will
 * be executed. (eg. `catch()`; `finally()`).
 *
 * @function
 * @group Idle
 * @group Promise
 * @group Rejected
 * @param reason - The rejection reason
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createIdleRejectedPromise: <T = unknown>(reason: any, timeout?: number) => IPromise<T>;

/**
 * Returns an idle Promise instance that is already resolved with the given value. If the value passed is
 * a promise then that promise is returned instead of creating a new asynchronous promise instance.
 * If a new instance is returned then any chained operations will execute __asynchronously__ using the
 * `requestIdleCallback` API (if available) with the optional provided timeout value to schedule when
 * the chained items will be executed. (eg. `then()`; `finally()`).
 *
 * @function
 * @group Idle
 * @group Promise
 * @group Resolved
 * @param value - The value to be used by this `Promise`. Can also be a `Promise` or a thenable to resolve.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createIdleResolvedPromise: <T>(value: T, timeout?: number) => IPromise<T>;

/**
 * Returns a single asynchronous Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations __asynchronously__ using the optional
 * provided timeout value to schedule when the chained items will be executed, or if the input contains no promises.
 * It rejects immediately upon any of the input promises rejected or non-promises throwing an error,
 * and will reject with this first rejection message / error.
 * If the runtime doesn't support the Promise.all it will fallback back to an asynchronous Promise implementation.
 * @group Alias
 * @group Promise
 * @group All
 * @group Native
 * @param input - The array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 * @returns
 * <ul>
 * <li> An already resolved `Promise`, if the input passed is empty.
 * <li> A pending `Promise` in all other cases. This returned promise is then resolved/rejected __synchronously__
 * (as soon as the pending items is empty) when all the promises in the given input have resolved, or if any of the
 * promises reject.
 * </ul>
 */
export declare function createNativeAllPromise<T>(input: Iterable<PromiseLike<T>>, timeout?: number): IPromise<T[]>;

/**
 * Returns a single asynchronous Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations using {@link createNativePromise | native}
 * environment promise implementation, if the runtime does not provide any native then the optional provided
 * timeout value will be used to schedule when the chained items will be executed or if the input contains no promises.
 * It will resolve only after all of the input promises have either resolved or rejected, and will resolve with an array
 * of {@link IPromiseResult } objects that each describe the outcome of each promise.
 * @since 0.5.0
 * @group Alias
 * @group Promise
 * @group AllSettled
 * @group Native
 * @param values - The iterator of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A pending `Promise` that will resolve to an array of {@link IPromiseResult } objects that each describe the outcome of each promise.
 *
 * @example
 * ```ts
 * const promises = [
 *   createNativeResolvedPromise(1),
 *   createNativeResolvedPromise(2),
 *   createNativeResolvedPromise(3),
 *   createNativeRejectedPromise("error"),
 * ];
 *
 * const results = await createNativeAllSettledPromise(promises);
 *
 * // results is:
 * // [
 * //   { status: "fulfilled", value: 1 },
 * //   { status: "fulfilled", value: 2 },
 * //   { status: "fulfilled", value: 3 },
 * //   { status: "rejected", reason: "error" }
 * // ]
 * ```
 */
export declare function createNativeAllSettledPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<IPromiseResult<Awaited<T>>[]>;

/**
 * The `createNativeAnyPromise` method takes an iterable of promises as input and returns a single Promise.
 * This returned promise fulfills when any of the input's promises fulfills, with this first fulfillment value.
 * It rejects when all of the input's promises reject (including when an empty iterable is passed), with an
 * AggregateError containing an array of rejection reasons.
 * @since 0.5.0
 * @group Alias
 * @group Promise
 * @group Any
 * @group Native
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A new Promise that is:
 * - Already rejected, if the iterable passed is empty.
 * - Asynchronously fulfilled, when any of the promises in the given iterable fulfills. The fulfillment value
 * is the fulfillment value of the first promise that was fulfilled.
 * - Asynchronously rejected, when all of the promises in the given iterable reject. The rejection reason is
 * an AggregateError containing an array of rejection reasons in its errors property. The errors are in the
 * order of the promises passed, regardless of completion order. If the iterable passed is non-empty but
 * contains no pending promises, the returned promise is still asynchronously (instead of synchronously)
 * rejected.
 */
export declare function createNativeAnyPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Creates a Promise instance that when resolved or rejected will execute it's pending chained operations using the
 * available native Promise implementation.
 * If runtime does not support native `Promise` class (or no polyfill is available) this function will fallback to using
 * `createAsyncPromise` which will resolve them __asynchronously__ using the optional provided timeout value to
 * schedule when the chained items will be executed.
 * @group Alias
 * @group Promise
 * @group Native
 * @param executor - The function to be executed during the creation of the promise. Any errors thrown in the executor will
 * cause the promise to be rejected. The return value of the executor is always ignored
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare function createNativePromise<T>(executor: PromiseExecutor<T>, timeout?: number): IPromise<T>;

/**
 * The `createNativeRacePromise` method takes an array of promises as input and returns a single Promise. This returned promise
 * settles with the eventual state of the first promise that settles.
 * @description The `createNativeRacePromise` method is one of the promise concurrency methods. It's useful when you want the first
 * async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
 * If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race() will settle to
 * the first of these values found in the iterable.
 * @since 0.5.0
 * @group Alias
 * @group Promise
 * @group Race
 * @group Native
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A Promise that settles with the eventual state of the first promise in the iterable to settle. In other words, it fulfills if the
 * first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever
 * if the iterable passed is empty. If the iterable passed is non-empty but contains no pending promises, the returned promise will settle
 * asynchronously.
 */
export declare function createNativeRacePromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Returns a single asynchronous Promise instance that is already rejected with the given reason.
 * Any chained operations will execute __asynchronously__ using the optional timeout value to schedule
 * when then chained items will be executed. (eg. `catch()`; `finally()`).
 *
 * @function
 * @group Alias
 * @group Promise
 * @group Rejected
 * @group Native
 * @param reason - The rejection reason
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createNativeRejectedPromise: <T = unknown>(reason: any, timeout?: number) => Promise<T>;

/**
 * Returns a single asynchronous Promise instance that is already resolved with the given value. If the value passed is
 * a promise then that promise is returned instead of creating a new asynchronous promise instance.
 * If a new instance is returned then any chained operations will execute __asynchronously__ using the optional
 * timeout value to schedule when the chained items will be executed.(eg. `then()`; `finally()`).
 *
 * @function
 * @group Alias
 * @group Promise
 * @group Resolved
 * @group Native
 * @param value - The value to be used by this `Promise`. Can also be a `Promise` or a thenable to resolve.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createNativeResolvedPromise: <T>(value: T, timeout?: number) => Promise<T>;

/**
 * Creates a Promise instance using the current default promise creator that when resolved or rejected will execute
 * it's pending chained operations.
 * @group Alias
 * @group Promise
 * @param executor - The function to be executed during the creation of the promise. Any errors thrown in the executor will
 * cause the promise to be rejected. The return value of the executor is always ignored
 * @param timeout - [Optional] timeout to wait before processing the items, defaults to zero.
 */
export declare function createPromise<T>(executor: PromiseExecutor<T>, timeout?: number): IPromise<T>;

/**
 * The `createRacePromise` method takes an array of promises as input and returns a single Promise. This returned promise
 * settles with the eventual state of the first promise that settles.
 * @description The `createRacePromise` method is one of the promise concurrency methods. It's useful when you want the first
 * async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
 * If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race() will settle to
 * the first of these values found in the iterable.
 * @since 0.5.0
 * @group Alias
 * @group Promise
 * @group Race
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A Promise that settles with the eventual state of the first promise in the iterable to settle. In other words, it fulfills if the
 * first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever
 * if the iterable passed is empty. If the iterable passed is non-empty but contains no pending promises, the returned promise will settle
 * based on the current promise implementation.
 */
export declare function createRacePromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Returns a single asynchronous Promise instance that is already rejected with the given reason.
 * Any chained operations will execute __asynchronously__ using the optional timeout value to schedule
 * when then chained items will be executed. (eg. `catch()`; `finally()`).
 *
 * @function
 * @group Alias
 * @group Promise
 * @group Rejected
 * @param reason - The rejection reason
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createRejectedPromise: <T = unknown>(reason: any, timeout?: number) => IPromise<T>;

/**
 * Returns a single asynchronous Promise instance that is already resolved with the given value. If the value passed is
 * a promise then that promise is returned instead of creating a new asynchronous promise instance.
 * If a new instance is returned then any chained operations will execute __asynchronously__ using the optional
 * timeout value to schedule when the chained items will be executed.(eg. `then()`; `finally()`).
 *
 * @function
 * @group Alias
 * @group Promise
 * @group Resolved
 * @param value - The value to be used by this `Promise`. Can also be a `Promise` or a thenable to resolve.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
 */
export declare const createResolvedPromise: <T>(value: T, timeout?: number) => IPromise<T>;

/**
 * Returns a single synchronous Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations __synchronously__ in the same
 * execution cycle as the final operation pending promises have resolved, or if the input contains no promises.
 * It rejects immediately upon any of the input promises rejected or non-promises throwing an error,
 * and will reject with this first rejection message / error.
 * When resolved or rejected any additional chained operations will execute __synchronously__ at the point of
 * being added (eg. `then()`; `catch()`; `finally()`).
 *
 * @function
 * @group Synchronous
 * @group Promise
 * @group All
 * @param input - The array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @returns
 * <ul>
 * <li> An already resolved `Promise`, if the input passed is empty.
 * <li> A pending `Promise` in all other cases. This returned promise is then resolved/rejected __synchronously__
 * (as soon as the pending items is empty) when all the promises in the given input have resolved, or if any of the
 * promises reject.
 * </ul>
 */
export declare const createSyncAllPromise: <T>(input: Iterable<PromiseLike<T>>) => IPromise<T[]>;

/**
 * Returns a single Promise instance that resolves to an array of the results from the input promises.
 * This returned promise will resolve and execute it's pending chained operations based on the
 * {@link createSyncPromise | synchronous} promise implementation. Any chained operations will execute
 * __synchronously__ in the same execution cycle as the final operation pending promises have resolved,
 * or if the input contains no promises. It will resolve only after all of the input promises have either
 * resolved or rejected, and will resolve with an array of {@link IPromiseResult } objects that each describe
 * the outcome of each promise.
 * @since 0.5.0
 * @group Synchronous
 * @group Promise
 * @group AllSettled
 * @param values - The iterator of promises to wait to be resolved / rejected before resolving or rejecting the new promise
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A pending `Promise` that will resolve to an array of {@link IPromiseResult } objects that each describe the outcome of each promise.
 *
 * @example
 * ```ts
 * const promises = [
 *   createResolvedPromise(1),
 *   createResolvedPromise(2),
 *   createResolvedPromise(3),
 *   createRejectedPromise("error"),
 * ];
 *
 * const results = await createAllSettledPromise(promises);
 *
 * // results is:
 * // [
 * //   { status: "fulfilled", value: 1 },
 * //   { status: "fulfilled", value: 2 },
 * //   { status: "fulfilled", value: 3 },
 * //   { status: "rejected", reason: "error" }
 * // ]
 * ```
 */
export declare function createSyncAllSettledPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<IPromiseResult<Awaited<T>>[]>;

/**
 * The `createSyncAnyPromise` method takes an iterable of promises as input and returns a single Promise.
 * This returned promise fulfills when any of the input's promises fulfills, with this first fulfillment value.
 * It rejects when all of the input's promises reject (including when an empty iterable is passed), with an
 * AggregateError containing an array of rejection reasons.
 * @since 0.5.0
 * @group Synchronous
 * @group Promise
 * @group Any
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A new Promise that is:
 * - Already rejected, if the iterable passed is empty.
 * - Asynchronously fulfilled, when any of the promises in the given iterable fulfills. The fulfillment value
 * is the fulfillment value of the first promise that was fulfilled.
 * - Asynchronously rejected, when all of the promises in the given iterable reject. The rejection reason is
 * an AggregateError containing an array of rejection reasons in its errors property. The errors are in the
 * order of the promises passed, regardless of completion order. If the iterable passed is non-empty but
 * contains no pending promises, the returned promise is still asynchronously (instead of synchronously)
 * rejected.
 */
export declare function createSyncAnyPromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Creates a synchronous Promise instance that when resolved or rejected will execute it's pending chained operations
 * __synchronously__ in the same execution cycle as the operation that calls the `executors`, `resolve` or `reject` functions.
 *
 * @group Synchronous
 * @group Promise
 * @param executor - The function to be executed during the creation of the promise. Any errors thrown in the executor will
 * cause the promise to be rejected. The return value of the executor is always ignored
 */
export declare function createSyncPromise<T>(executor: PromiseExecutor<T>): IPromise<T>;

/**
 * The `createSyncRacePromise` method takes an array of promises as input and returns a single Promise. This returned promise
 * settles with the eventual state of the first promise that settles.
 * @description The `createSyncRacePromise` method is one of the promise concurrency methods. It's useful when you want the first
 * async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
 * If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race() will settle to
 * the first of these values found in the iterable.
 * @since 0.5.0
 * @group Synchronous
 * @group Promise
 * @group Race
 * @param values - An iterable object of promises.
 * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
 * @returns A Promise that settles with the eventual state of the first promise in the iterable to settle. In other words, it fulfills if the
 * first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever
 * if the iterable passed is empty. If the iterable passed is non-empty but contains no pending promises, the returned promise will settle
 * synchronously.
 */
export declare function createSyncRacePromise<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;

/**
 * Returns a single synchronous Promise instance that is already rejected with the given reason.
 * Any chained operations will execute __synchronously__ at the point of being added (eg. `catch()`; `finally()`).
 *
 * @function
 * @group Synchronous
 * @group Promise
 * @group Rejected
 * @param reason - The rejection reason
 */
export declare const createSyncRejectedPromise: <T = unknown>(reason: any) => IPromise<T>;

/**
 * Returns a single synchronous Promise instance that is already resolved with the given value. If the value passed is
 * a promise then that promise is returned instead of creating a new synchronous promise instance.
 * If a new instance is returned then any chained operations will execute __synchronously__ at the point of being
 * added (calling `then()`).
 *
 * @function
 * @group Synchronous
 * @group Promise
 * @group Resolved
 * @param value - The value to be used by this `Promise`. Can also be a `Promise` or a thenable to resolve.
 */
export declare const createSyncResolvedPromise: <T>(value: T) => IPromise<T>;

/**
 * Create a Task Scheduler using the optional promise implementation and scheduler name.
 * The newPromise can be any value promise creation function, where the execution of the
 * queued tasks will be processed based on how the promise implementation processes it's
 * chained promises (asynchrounsly; synchronously; idle processing, etc)
 *
 * The functions used to start each task my return a result (synchronous execution) or an
 * {@link IPromise}, `PromiseLike` or `Promise` result (asynchronous execution).
 *
 * Each task is executed in the order that it was queued and the provided `startTask` function
 * will not be called until all previous tasks have completed (whther they resolve or reject).
 * The result from any previous task does not affect and is not passed to any later scheduled
 * task, if you need this capability then your `startTask` functions will need to co-operate to
 * share any common context.
 *
 * By default, queued tasks which have either been "waiting" to run or have been running longer
 * then 10 minutes will be Auto-Rejected to try and free up resources. If a task is running when
 * it rejected then it will continue to "run" based on whatever operation it's `startTask` is
 * performing. If a task has not yet had it's `startTask` function called it will never get called.
 * In both cases the `IPromise` returned by the call to {@link ITaskScheduler.queue | queue} the
 * task will be `rejected`. You can change this default time, including disabling completly via
 * the {@link ITaskScheduler.setStaleTimeout | setStaleTimeout}
 * function.
 * @since 0.2.0
 * @group Scheduler
 * @param newPromise - The function to use for creating a new promise when required, if not
 * provided this will default to {@link createPromise} which will use the default registered
 * promise creation function which defaults to runtime native promises or async Promise if not
 * supported by the runtime.
 * @param name - The name you want to associated with this scheduler, mostly useful for debugging
 * @returns A new ITaskScheduler instance
 * @example
 * ```ts
 * let scheduler = createTaskScheduler();
 *
 * // Schedule a task using the ts-async helper promise functions
 * scheduler.queue(() => {
 *     return createPromise((resolve, reject) => {
 *         scheduleTimeout(() => {
 *             // Do something after a delay
 *         }, 100);
 *     });
 * });
 *
 * // Schedule an asynchronous task which uses async/await
 * scheduler.queue(async () => {
 *     // This task will only execute after the previous task has completed
 *     await performAnotherAsyncTask();
 * });
 *
 * // Schedule a synchronous task that executes and completes immediately
 * scheduled.queue(() => {
 *     // Do some synchronous task
 *     return 42;
 * });
 *
 * // Schedule an asynchronous task which returns a promise
 * scheduled.queue(() => {
 *     return doAwait(fetch("https://github.com/nevware21/ts-async/blob/main/README.md"), (response) => {
 *         let theReadMe = response.text();
 *         // Do something with the readme
 *     });
 * });
 * ```
 */
export declare function createTaskScheduler(newPromise?: <T>(executor: PromiseExecutor<T>, timeout?: number) => IPromise<T>, name?: string): ITaskScheduler;

/**
 * Creates a Promise instance that resolve or reject after the specified timeout.
 * @since 0.5.0
 * @group Timeout
 * @group Promise
 * @param timeout - The timeout in milliseconds to wait before resolving or rejecting the promise.
 * @param resolveReject - [Optional] If true the promise will resolve, otherwise it will reject.
 * @param message - [Optional] The message to use when rejecting the promise, if not supplied (or
 * undefined) the default message will be used.
 * @returns A promise that will resolve or reject after the specified timeout.
 * @example
 * ```ts
 * // Rejects after 100ms with default message
 * const result = await createTimeoutPromise(100);
 * // Throws an Error: Timeout of 100ms exceeded
 *
 * // Resolves after 100ms with default message
 * const result = await createTimeoutPromise(100, true);
 * console.log(result); // Timeout of 100ms exceeded
 *
 * // Rejects after 100ms with default message
 * const result = await createTimeoutPromise(100, false);
 * // throws an Error: Timeout of 100ms exceeded
 *
 * // Resolves after 100ms with default message
 * const result = await createTimeoutPromise(100, true);
 * console.log(result); // Timeout of 100ms exceeded
 *
 * // Rejects after 100ms with the message "Hello"
 * const result = await createTimeoutPromise(100, false, "Hello");
 * // throws an Error: Hello
 *
 * // Resolves after 100ms with the message "Hello"
 * const result = await createTimeoutPromise(100, true, "Hello");
 * console.log(result); // Hello
 *
 * // Resolves after 100ms with the message "Hello"
 * doAwait(createTimeoutPromise(100, true, "Hello"), (result) => {
 *  console.log(result); // Hello
 * });
 *
 * // Rejects after 100ms with the message "Hello"
 * doAwait(createTimeoutPromise(100, false, "Hello"), (result) => {
 *   // Not called
 * }, (err) => {
 *   console.log(err); // Hello
 * });
 *
 * // Rejects after 100ms with the message "Hello"
 * doAwaitResult(createTimeoutPromise(100, false, "Hello"), (result) => {
 *   console.log(result.rejected); // true
 *   console.log(result.reason); // Hello
 * });
 * ```
 */
export declare function createTimeoutPromise<T = any>(timeout: number, resolveReject?: boolean, message?: T): IPromise<T>;

/**
 * Wait for the promise to resolve or reject, if resolved the callback function will be called with it's value and if
 * rejected the rejectFn will be called with the reason. If the passed promise argument is not a promise the callback
 * will be called synchronously with the value.
 * @group Await Helper
 * @param value - The value or promise like value to wait for
 * @param resolveFn - The callback to call on the promise successful resolving.
 * @param rejectFn - The callback to call when the promise rejects
 * @param finallyFn - The callback to call once the promise has resolved or rejected
 * @returns The passed value, if it is a promise and there is either a resolve or reject handler
 * then it will return a chained promise with the value from the resolve or reject handler (depending
 * whether it resolve or rejects)
 * @example
 * ```ts
 * let promise = createPromise<number>((resolve, reject) => {
 *     resolve(42);
 * });
 *
 * // Handle via a chained promise
 * let chainedPromise = promise.then((value) => {
 *     // Do something with the value
 * });
 *
 * // Handle via doAwait
 * doAwait(promise, (value) => {
 *     // Do something with the value
 * });
 *
 * // It can also handle the raw value, so you could process the result of either a
 * // synchrounous return of the value or a Promise
 * doAwait(42, (value) => {
 *     // Do something with the value
 * });
 * ```
 */
export declare function doAwait<T, TResult1 = T, TResult2 = never>(value: T | IPromise<T> | PromiseLike<T>, resolveFn: ResolvedPromiseHandler<T, TResult1>, rejectFn?: RejectedPromiseHandler<TResult2>, finallyFn?: FinallyPromiseHandler): TResult1 | TResult2 | IPromise<TResult1 | TResult2>;

/**
 * Wait for the promise to resolve or reject, if resolved the callback function will be called with it's value and if
 * rejected the rejectFn will be called with the reason. If the passed promise argument is not a promise the callback
 * will be called synchronously with the value.
 * @group Await Helper
 * @param value - The value or promise like value to wait for
 * @param resolveFn - The callback to call on the promise successful resolving.
 * @param rejectFn - The callback to call when the promise rejects
 * @param finallyFn - The callback to call once the promise has resolved or rejected
 * @returns The passed value, if it is a promise and there is either a resolve or reject handler
 * then it will return a chained promise with the value from the resolve or reject handler (depending
 * whether it resolve or rejects)
 * @example
 * ```ts
 * let promise = createPromise<number>((resolve, reject) => {
 *     resolve(42);
 * });
 *
 * // Handle via a chained promise
 * let chainedPromise = promise.then((value) => {
 *     // Do something with the value
 * });
 *
 * // Handle via doAwait
 * doAwait(promise, (value) => {
 *     // Do something with the value
 * });
 *
 * // It can also handle the raw value, so you could process the result of either a
 * // synchrounous return of the value or a Promise
 * doAwait(42, (value) => {
 *     // Do something with the value
 * });
 * ```
 */
export declare function doAwait<T, TResult1 = T, TResult2 = never>(value: T | PromiseLike<T>, resolveFn: ResolvedPromiseHandler<T, TResult1>, rejectFn?: RejectedPromiseHandler<TResult2>, finallyFn?: FinallyPromiseHandler): TResult1 | TResult2 | PromiseLike<TResult1 | TResult2>;

/**
 * Helper to coallesce the promise resolved / reject into a single callback to simplify error handling.
 * @group Await Helper
 * @param value - The value or promise like value to wait
 * @param cb - The callback function to call with the resulting value, if the value is not a
 * promise like value then the callback is called synchronously, if the value is a promise then
 * the callback will be called once the promise completes the resulting value will be passed as an
 * IAwaitResponse instance, it will be called whether any promise resolves or rejects.
 * @returns The value returned by the `cb` callback function, if the value is a promise then the return value
 * of the callback will be returned as a promise whether the callback returns a promise or not.
 * @example
 * ```ts
 * let promise = createPromise<number>((resolve, reject) => {
 *     resolve(42);
 * });
 *
 * // Handle via doAwaitResponse
 * doAwaitResponse(promise, (value) => {
 *     if (!value.rejected) {
 *          // Do something with the value
 *     } else {
 *         // Do something with the reason
 *     }
 * });
 *
 * // It can also handle the raw value, so you could process the result of either a
 * // synchrounous return of the value or a Promise
 * doAwaitResponse(42, (value) => {
 *     if (!value.rejected) {
 *         // Do something with the value
 *     } else {
 *        // This will never be true as the value is not a promise
 *     }
 * });
 * ```
 */
export declare function doAwaitResponse<T, TResult1 = T, TResult2 = never>(value: T | IPromise<T> | PromiseLike<T>, cb: (response: AwaitResponse<T | TResult1>) => T | TResult1 | TResult2 | IPromise<T | TResult1 | TResult2> | PromiseLike<T | TResult1 | TResult2>): T | TResult1 | TResult2 | IPromise<T | TResult1 | TResult2>;

/**
 * Helper to coallesce the promise resolved / reject into a single callback to simplify error handling.
 * @group Await Helper
 * @param value - The value or promise like value to wait for
 * @param cb - The callback function to call with the resulting value, if the value is not a
 * promise like value then the callback is called synchronously, if the value is a promise then
 * the callback will be called once the promise completes the resulting value will be passed as an
 * IAwaitResponse instance, it will be called whether any promise resolves or rejects.
 * @returns The value returned by the `cb` callback function, if the value is a promise then the return value
 * of the callback will be returned as a promise whether the callback returns a promise or not.
 * @example
 * ```ts
 * let promise = createPromise<number>((resolve, reject) => {
 *     resolve(42);
 * });
 *
 * // Handle via doAwaitResponse
 * doAwaitResponse(promise, (value) => {
 *     if (!value.rejected) {
 *          // Do something with the value
 *     } else {
 *         // Do something with the reason
 *     }
 * });
 *
 * // It can also handle the raw value, so you could process the result of either a
 * // synchrounous return of the value or a Promise
 * doAwaitResponse(42, (value) => {
 *     if (!value.rejected) {
 *         // Do something with the value
 *     } else {
 *        // This will never be true as the value is not a promise
 *     }
 * });
 * ```
 */
export declare function doAwaitResponse<T, TResult1 = T, TResult2 = never>(value: T | PromiseLike<T>, cb: (response: AwaitResponse<T | TResult1>) => T | TResult1 | TResult2 | PromiseLike<T | TResult1 | TResult2>): T | TResult1 | TResult2 | PromiseLike<T | TResult1 | TResult2>;

/**
 * Wait for the promise to resolve or reject and then call the finallyFn. If the passed promise argument is not a promise the callback
 * will be called synchronously with the value. If the passed promise doesn't implement finally then a finally implementation will be
 * simulated using then(..., ...).
 * @group Await Helper
 * @param value - The value or promise like value to wait for
 * @param finallyFn - The finally function to call once the promise has resolved or rejected
 */
export declare function doFinally<T>(value: T | IPromise<T> | PromiseLike<T>, finallyFn: FinallyPromiseHandler): T | IPromise<T>;

/**
 * Wait for the promise to resolve or reject and then call the finallyFn. If the passed promise argument is not a promise the callback
 * will be called synchronously with the value. If the passed promise doesn't implement finally then a finally implementation will be
 * simulated using then(..., ...).
 * @group Await Helper
 * @param value - The value or promise like value to wait for
 * @param finallyFn - The finally function to call once the promise has resolved or rejected
 */
export declare function doFinally<T>(value: T | PromiseLike<T>, finallyFn: FinallyPromiseHandler): T | PromiseLike<T>;

/**
 * Performs a while loop, calling the provided `callbackFn` function until the `state.isDone`
 * property is set to `true` or the optional `isDOneFn` returns `true`. The callback function will
 * receive a single {@link IWhileState | state} argument and may return either a value or a promise,
 * if a promise is returned the while loop will wait until the promise is resolved before calling
 * the callback function again. If the callback function never returns a promise the while loop
 * will be executed synchronous and last value returned by the callback will be returned, if the
 * callback function returns a promise the while loop will be asynchronous and an {@link IPromise}
 * will be returned and resolved with the last value returned by the callback or rejected if the
 * callback promise rejects or throws an error.
 * @since 0.5.0
 * @group Loop
 * @typeParam T - Identifies the element type returned by the callback function.
 * @param callbackFn - A function that will be called until the `state.isDone` flag is set to `true`
 * the function will receive a single {@link IWhileState | state} argument. The callback function
 * may return either a value or a promise, if a promise is returned the while loop will wait
 * until the promise is resolved before calling the callback function again.
 * @param isDoneFn - An optional function that will be called after the callback function is called,
 * that can be used to stop the while loop. The function will receive a single {@link IWhileState | state}
 * argument. If the function returns `true` the while loop will stop, otherwise the while loop will continue.
 * @param thisArg - An object to which the this keyword can refer in the callbackfn function.
 * If thisArg is omitted, null or undefined the array will be used as the this value.
 * @remarks
 * - If an `isDoneFn` is provided the `state.isDone` property will be set to the provided value and
 * is accessible withing the callback function. The callbackFn may overwrite the value of the
 * `state.isDone` property within the callback function with a boolean value or another function that
 * returns a boolean value.
 * - The callback function is called until until the `state.isDone` property is set to `true` or if
 * `state.isDone` is a function until the function returns `true`.
 * - The callback function will receive a single {@link IWhileState | state} argument that contains
 * the following properties:
 *  - `iter` - The zero-based iteration count, which is incremented after each call to the `callbackFn`
 * and any `isDone` function (if provided), the `iter` property is accessible withing the callback
 * function and may be overwritten within the callback function.
 * - `res` - The last resolved result value returned by the `callbackFn` function.
 * - `isDone` - A boolean value or a callback function that will be called to check if the while loop
 * should stop, the `isDone` property is accessible withing the callback function and may be
 * overwritten within the callback function.
 * - The callback function may return either a value or a promise, if a promise is returned the while
 * loop will wait until the promise is resolved before calling the callback function again.
 * - If the callback function throws an error when executing `synchronously` the exception will
 * also be thrown `synchronously` otherwise the returned promise will be rejected with the error.
 * @example
 * ```ts
 * // Synchronous example
 * const result = doWhileAsync((state) => { // Note: DO NOT use async here unless you use await withing the function
 *    if (state.idx < 10) {
 *      // Logs each iteration index (will be called synchronously)
 *      // Logs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *      console.log(state.idx);
 *   } else {
 *     state.isDone = true;
 *     return "Hello";
 *  }
 * });
 *
 * console.log(result); // returns Hello after logging 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *
 * // Synchronous example with isDoneFn
 * const result = doWhileAsync((state) => { // Note: DO NOT use async here unless you use await withing the function
 *    if (state.idx < 10) {
 *      // Logs each iteration index (will be called synchronously)
 *      // Logs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *      console.log(state.idx);
 *   } else {
 *     return "Hello";
 *  }
 * }, (state) => state.idx > 10);
 * console.log(result); // returns Hello after logging 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *
 * // Asynchronous examples
 * const result = await doWhileAsync((state) => { // Note: DO NOT use async here unless you use await withing the function
 *   if (state.idx < 10) {
 *     // Logs each iteration index
 *     // Logs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 calling the callback function synchronously
 *     console.log(state.idx);
 *     // Returning a promise will cause `doWhileAsync` to return a promise to the caller
 *     // and wait for the promise to resolve before calling the callback function again.
 *     return createTimeoutPromise(10, true, state.idx);
 *   }
 *
 *   state.isDone = true;
 *   return createResolvedPromise("Darkness");
 * });
 * console.log(result); // Darkness
 *
 * // Asynchronous example with isDoneFn
 * const result = await doWhileAsync((state) => { // Note: DO NOT use async here unless you use await withing the function
 *   if (state.idx < 10) {
 *     // Logs each iteration index
 *     // Logs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 calling the callback function synchronously
 *     console.log(state.idx);
 *     // Returning a promise will cause `doWhileAsync` to return a promise to the caller
 *     // and wait for the promise to resolve before calling the callback function again.
 *     return createTimeoutPromise(10, true, state.idx);
 *   }
 *
 *   return createResolvedPromise("Darkness");
 * }, (state) => state.idx > 10);
 * console.log(result); // returns Darkness after logging 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *
 * // Combination Synchronous and Asynchronous example
 * const result = await doWhileAsync((state) => { // Note: DO NOT use async here unless you use await withing the function
 *   if (state.idx < 10) {
 *     // Logs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *     // Logs each iteration index (will be called synchronously)
 *     console.log(state.idx);
 *   } else {
 *     state.isDone = true;
 *     // Returning a promise will cause `doWhileAsync` to return a promise to the caller
 *     // and wait for the promise to resolve before resolving the returned promise.
 *     return createResolvedPromise("my old friend");
 *   }
 * });
 *
 * console.log(result); // my old friend
 *
 * // Asynchronous example using await
 * const result = await doWhileAsync(async (state) => {
 *   if (state.idx < 10) {
 *     // Logs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *     // Logs each iteration index (will be called synchronously)
 *     await createTimeoutPromise(10, true, state.idx);
 *   } else {
 *     state.isDone = true;
 *     // Returning a promise will cause `doWhileAsync` to return a promise to the caller
 *     // and wait for the promise to resolve before resolving the returned promise.
 *     return await createResolvedPromise("my old friend");
 *   }
 * });
 *
 * console.log(result); // my old friend
 *
 * // Asynchronous example using await and dynamically setting the isDone function
 * const result = await doWhileAsync(async (state) => {
 *   // dynamically set the isDone function
 *   if (state.idx < 10) {
 *     state.isDone = () => return false;
 *     // Logs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
 *     // Logs each iteration index (will be called synchronously)
 *     await createTimeoutPromise(10, true, state.idx);
 *   } else {
 *     state.isDone = () => return true;
 *     // Returning a promise will cause `doWhileAsync` to return a promise to the caller
 *     // and wait for the promise to resolve before resolving the returned promise.
 *     return await createResolvedPromise("my old friend");
 *   }
 * });
 *
 * console.log(result); // my old friend
 * ```
 */
export declare function doWhileAsync<T>(callbackFn: (state: IWhileState<T>) => T | IPromise<T> | PromiseLike<T>, isDoneFn?: (state: IWhileState<T>) => boolean | void | IPromise<boolean | void> | PromiseLike<boolean | void>, thisArg?: any): T | IPromise<T>;

/**
 * A function to asynchronously execute when the promise becomes settled (fulfilled or rejected).
 * If the function returns a promise, the resulting promise will wait for that promise to settle
 * before continuing. If the returned promise is rejected, the resulting promise is rejected with
 * the same reason. Any other returned value, or the fulfilled value of the returned promise, is ignored.
 */
export declare type FinallyPromiseHandler = (() => void) | undefined | null;

/**
 * Create a Promise object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value.
 * This interface definition, closely mirrors the typescript / javascript PromiseLike<T> and Promise<T> definitions as well as providing
 * simular functions as that provided by jQuery deferred objects.
 *
 * The returned Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers
 * with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous
 * methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point
 * in the future.
 *
 * A Promise is in one of these states:
 * <ul>
 * <li> pending: initial state, neither fulfilled nor rejected.
 * <li> fulfilled: meaning that the operation was completed successfully.
 * <li> rejected: meaning that the operation failed.
 * </ul>
 *
 * A pending promise can either be fulfilled with a value or rejected with a reason (error). When either of these options happens, the
 * associated handlers queued up by a promise's then method are called synchronously. If the promise has already been fulfilled or rejected
 * when a corresponding handler is attached, the handler will be called synchronously, so there is no race condition between an asynchronous
 * operation completing and its handlers being attached.
 *
 * As the `then()` and `catch()` methods return promises, they can be chained.
 * @typeParam T - Identifies the expected return type from the promise
 */
export declare interface IPromise<T> extends PromiseLike<T>, Promise<T> {
    /**
     * Returns a string representation of the current state of the promise. The promise can be in one of four states.
     * <ul>
     * <li> <b>"pending"</b>: The promise is not yet in a completed state (neither "rejected"; or "resolved").</li>
     * <li> <b>"resolved"</b>: The promise is in the resolved state.</li>
     * <li> <b>"rejected"</b>: The promise is in the rejected state.</li>
     * </ul>
     * @example
     * ```ts
     * let doResolve;
     * let promise: IPromise<any> = createSyncPromise((resolve) => {
     *  doResolve = resolve;
     * });
     *
     * let state: string = promise.state();
     * console.log("State: " + state);      // State: pending
     * doResolve(true);                     // Promise will resolve synchronously as it's a synchronous promise
     * console.log("State: " + state);      // State: resolved
     * ```
     */
    state?: string;
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onResolved - The callback to execute when the Promise is resolved.
     * @param onRejected - The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of which ever callback is executed.
     * @example
     * ```ts
     * const promise1 = createPromise((resolve, reject) => {
     *   resolve('Success!');
     * });
     *
     * promise1.then((value) => {
     *   console.log(value);
     *   // expected output: "Success!"
     * });
     * ```
     */
    then<TResult1 = T, TResult2 = never>(onResolved?: ResolvedPromiseHandler<T, TResult1>, onRejected?: RejectedPromiseHandler<TResult2>): IPromise<TResult1 | TResult2>;
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onResolved - The callback to execute when the Promise is resolved.
     * @param onRejected - The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of which ever callback is executed.
     * @example
     * ```ts
     * const promise1 = createPromise((resolve, reject) => {
     *   resolve('Success!');
     * });
     *
     * promise1.then((value) => {
     *   console.log(value);
     *   // expected output: "Success!"
     * });
     * ```
     */
    then<TResult1 = T, TResult2 = never>(onResolved?: ResolvedPromiseHandler<T, TResult1>, onRejected?: RejectedPromiseHandler<TResult2>): PromiseLike<TResult1 | TResult2>;
    /**
     * Attaches callbacks for the resolution and/or rejection of the Promise.
     * @param onResolved - The callback to execute when the Promise is resolved.
     * @param onRejected - The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of which ever callback is executed.
     * @example
     * ```ts
     * const promise1 = createPromise((resolve, reject) => {
     *   resolve('Success!');
     * });
     *
     * promise1.then((value) => {
     *   console.log(value);
     *   // expected output: "Success!"
     * });
     * ```
     */
    then<TResult1 = T, TResult2 = never>(onResolved?: ResolvedPromiseHandler<T, TResult1>, onRejected?: RejectedPromiseHandler<TResult2>): IPromise<TResult1 | TResult2>;
    /**
     * Attaches a callback for only the rejection of the Promise.
     * @param onRejected - The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of the callback.
     * @example
     * ```ts
     * const promise1 = createPromise((resolve, reject) => {
     *   throw 'Uh-oh!';
     * });
     *
     * promise1.catch((error) => {
     *   console.error(error);
     * });
     * // expected output: Uh-oh!
     * ```
     */
    catch<TResult = never>(onRejected?: ((reason: any) => TResult | IPromise<TResult>) | undefined | null): IPromise<T | TResult>;
    /**
     * Attaches a callback for only the rejection of the Promise.
     * @param onRejected - The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of the callback.
     * @example
     * ```ts
     * const promise1 = createPromise((resolve, reject) => {
     *   throw 'Uh-oh!';
     * });
     *
     * promise1.catch((error) => {
     *   console.error(error);
     * });
     * // expected output: Uh-oh!
     * ```
     */
    catch<TResult = never>(onRejected?: ((reason: any) => TResult | IPromise<TResult>) | undefined | null): PromiseLike<T | TResult>;
    /**
     * Attaches a callback for only the rejection of the Promise.
     * @param onRejected - The callback to execute when the Promise is rejected.
     * @returns A Promise for the completion of the callback.
     * @example
     * ```ts
     * const promise1 = createPromise((resolve, reject) => {
     *   throw 'Uh-oh!';
     * });
     *
     * promise1.catch((error) => {
     *   console.error(error);
     * });
     * // expected output: Uh-oh!
     * ```
     */
    catch<TResult = never>(onRejected?: ((reason: any) => TResult | IPromise<TResult>) | undefined | null): IPromise<T | TResult>;
    /**
     * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
     * resolved value cannot be modified from the callback.
     * @param onfinally - A function to asynchronously execute when this promise becomes settled.
     * If the function returns a promise, the resulting promise will wait for that promise to settle
     * before continuing. If the returned promise is rejected, the resulting promise is rejected with
     * the same reason. Any other returned value, or the fulfilled value of the returned promise, is ignored.
     * @returns A Promise for the completion of the callback.
     * @example
     * ```ts
     * function doFunction() {
     *   return createPromise((resolve, reject) => {
     *     if (Math.random() > 0.5) {
     *       resolve('Function has completed');
     *     } else {
     *       reject(new Error('Function failed to process'));
     *     }
     *   });
     * }
     *
     * doFunction().then((data) => {
     *     console.log(data);
     * }).catch((err) => {
     *     console.error(err);
     * }).finally(() => {
     *     console.log('Function processing completed');
     * });
     * ```
     */
    finally(onfinally?: FinallyPromiseHandler): IPromise<T>;
}

/**
 * The result of a promise. It can either be fulfilled with a value, or rejected with a reason.
 * @since 0.5.0
 * @group Promise
 * @typeParam T - The type of the fulfilled value.
 * @typeParam U - The type of the rejected reason.
 *
 * @example
 * ```ts
 * const result: IPromiseResult<number> = {
 *   status: "fulfilled",
 *   value: 42
 * };
 *
 * const result: IPromiseResult<number> = {
 *   status: "rejected",
 *   reason: "Hello Darkness"
 * };
 * ```
 */
export declare interface IPromiseResult<T> {
    /**
     * A string indicating whether the promise was fulfilled or rejected
     */
    status: "fulfilled" | "rejected";
    /**
     * The value that the promise was fulfilled with.
     */
    value?: T;
    /**
     * The reason that the promise was rejected with.
     */
    reason?: any;
}

/**
 * Defines a Task Scheduler that uses IPromise implementations to serialize the execution of the tasks.
 * Each added task will not get executed until the previous task has completed.
 * @since 0.2.0
 * @group Scheduler
 */
export declare interface ITaskScheduler {
    /**
     * Identifies if this scheduler is currently idle (`true`) or has waiting or currently processing tasks (`false`).
     * @example
     * ```ts
     * let scheduler = createTaskScheduler();
     *
     * // Check idle state
     * scheduler.idle;  // true
     *
     * let queuedTask = scheduler.queue(() => {
     *     // Return a promise
     *     return createPromise((resolve) => {
     *         // Wait some time then resolve
     *     });
     * });
     *
     * // Check idle state
     * scheduler.idle;  // false
     *
     * // Wait for the queued task to complete
     * await queuedTask;
     *
     * // Check idle state
     * scheduler.idle;  // true
     * ```
     */
    readonly idle: boolean;
    /**
     * Queue a task to be scheduled for execution, once the task has completed the returned IPromise
     * will be resolved / rejected
     * @param theTask - The function to call to start the task
     * @param taskName - The optional task name for the task, useful for debugging.
     * @param timeout - Specify a specific timeout for the task, the timeout will only apply once the task is started.
     * @returns A new promise that will be resolved (or rejected) once the task has been executed or aborted.
     * @example
     * ```ts
     * let scheduler = createTaskScheduler();
     *
     * // Schedule an async task, where the function returns a Promise or PromiseLike result
     * let queuedTask = scheduler.queue(runSomeAsyncTask());
     *
     * // Schedule an async task, where the function returns a Promise or PromiseLike result
     * let queuedTask2 = scheduler.queue(runAnotherAsyncTask());
     *
     * // Both queuedTask and queuedTask2 are Promise implementation (based on the type used by the scheduler)
     * // You can now treat these like any promose to wait for them to be resolve / rejected
     * // Somewhere else in your code using either `await`, `doAwait`, doAwaitResponse`, `doFinally`, `then`, `catch`
     * // or `finally`
     * doAwait(queuedTask, (result1) => {
     *     // queued task 1 is now complete
     *     // queued task 2 is now scheduled to run (or is already running)
     * });
     *
     * doAwait(queuedTask2, (result1) => {
     *     // Both task 1 and 2 have completed
     *     // As task 2 did not start until task 1 finished
     * });
     *
     * // This Will also work and will not cause a deadlock
     * // But task 2 will still not start until task 1 has completed
     * let task2Result = await queuedTask2;
     *
     * // Now get the task 1 response
     * let task1Result = await queuedTask1;
     * ```
     */
    queue: <T>(theTask: StartQueuedTaskFn<T>, taskName?: string, timeout?: number) => IPromise<T>;
    /**
     * Set the timeout to reject and remove any stale running tasks to avoid filling up memory
     * with blocked tasks.
     * @param staleTimeout - Identifies the maximum that a task can be running or waiting to start,
     * defaults to 10 minutes. If the value is set to zero or less the stale timeout will never
     * abort waiting tasks.
     * @param staleCheckPeriod - Identifes how oftem the queue's should be checked for stale tasks,
     * defaults to 1/10th of the staleTimeout when not specified. This directly sets the asynchronous
     * timeout value.
     * @example
     * ```ts
     * let secheduler = createTaskScheduler();
     *
     * // Set the stale task timeout to 1 second, this will check every 100ms
     * // for any long waiting / executing tasks and "reject" them.
     * scheduler.setStaleTimeout(1000);
     *
     * // Set the stale task timeout to 5 minutes (300 seconds), this will check every 1 minute (60 seconds)
     * // for any long waiting / executing tasks and "reject" them.
     * scheduler.setStaleTimeout(300000, 60000);
     * ```
     */
    setStaleTimeout: (staleTimeout: number, staleCheckPeriod?: number) => void;
}

/**
 * Calls the provided `callbackFn` function once for each element in the iterator or iterator returned by
 * the iterable and processed in the same order as returned by the iterator. As with the {@link arrForEachAsync}
 * you CAN stop or break the iteration by returning -1 from the `callbackFn` function.
 *
 * The order of processing is not reset if you add or remove elemenets to the iterator, the actual behavior will
 * depend on the iterator implementation.
 *
 * if the passed `iter` is both an Iterable\<T\> and Iterator\<T\> the Iterator\<T\> interface takes precedence. And if
 * an iterable and does not have a `Symbol.iterator` property then the `iter` will be used as the iterator.
 *
 * The `callbackFn` may execute `synchronously` or `asynchronously` and if the `callbackFn` returns a `Promise`
 * then the next iteration will not be called until the promise is resolved. If the `callbackFn` returns a `Promise`
 * that is rejected then the iteration will stop and the promise returned by iterForEachAsync will be rejected with
 * the same error.
 * @remarks
 * If Symbols are NOT supported then the iterable MUST be using the same polyFill for the well know symbols, as used
 * by the library. If the iterable is using a different polyFill then the `iter` MUST be an Iterator\<T\> and not an
 * Iterable\<T\>.
 * If you are targetting a mixed environment you SHOULD either
 * - only use the polyfill Symbol's provided by this library
 * - ensure that you add any symbol polyfills BEFORE these utilities
 * iterForOfAsync
 * @since 0.5.0
 * @group Loop
 * @group Iterator
 * @typeParam T - Identifies the element type of the iterator
 * @param iter - The iterator or iterable of elements to be searched.
 * @param callbackFn - A `asynchronous` or `synchronous` function that accepts up to three arguments. iterForEach
 * calls the callbackfn function one time for each element in the iterator.
 * @param thisArg - An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted,
 * null or undefined the iterator will be used as the this value.
 * @example
 * ```ts
 * const items = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7', 'item8', 'item9', 'item10'];
 * const copyItems = [];
 *
 * // using async / await
 * let result = await iterForOfAsync(items, async (value, index) => {
 *   copyItems.push(value);
 *   if (index === 5) {
 *     return -1; // Stop the iteration
 *   }
 *
 *   await createTimeoutPromise(100); // Wait 100ms before processing the next item, you could also just return the promise
 *  })
 *
 * console.log(result); // returns -1 if the loop was stopped, otherwise returns undefined
 *
 * // using doAwait
 * doAwait(iterForOfAsync(items, (value, index) => {
 *   copyItems.push(value);
 *   if (index === 5) {
 *     return -1; // Stop the iteration
 *   }
 *
 *   return createTimeoutPromise(100); // Wait 100ms before processing the next item, you could also just return the promise
 *  }), (result) => {
 *    console.log(result); // returns -1 if the loop was stopped, otherwise returns undefined
 *  });
 * ```
 */
export declare function iterForOfAsync<T = any>(iter: Iterator<T> | Iterable<T> | AsyncIterator<T> | AsyncIterable<T>, callbackFn: (value: T, count: number, iter?: Iterator<T> | AsyncIterator<T>) => void | number | IPromise<void | number>, thisArg?: any): void | number | IPromise<void | number>;

/**
 * The current state of the while loop while processing the callback function, this is
 * passed to eht callback function.
 * @typeParam T - Identifies the element type returned by the callback function.
 * @since 0.5.0
 */
export declare interface IWhileState<T> {
    /**
     * The number of milliseconds that have elapsed since January 1, 1970 00:00:00 UTC,
     * at the beginning of the while loop. This value is set at the beginning of the while
     * loop via [`utcNow()`](https://nevware21.github.io/ts-utils/typedoc/functions/utcNow.html)
     * (`Date.now()`) and is not updated during the execution of while loop.
     */
    st: number;
    /**
     * The zero-based iteration count, which is increased after each call to the callback.
     */
    iter: number;
    /**
     * The resolved result value returned by the callback function.
     */
    res?: T;
    /**
     * Callback to enable the caller stop the while loop.
     */
    isDone: boolean | ((state: IWhileState<T>) => boolean | void | IPromise<boolean | void> | PromiseLike<boolean | void>);
}

/**
 * A full polyfill for the Promise class.
 * Represents the completion of an asynchronous operation, and its resulting value.
 * @class PolyPromise
 * @description The `PolyPromise` class is a polyfill for the native Promise class. It provides a way to work with asynchronous operations in a more manageable way.
 * @since 0.5.0
 * @group Polyfill
 * @group Promise
 */
export declare let PolyPromise: PolyPromiseConstructor;

/**
 * The PolyPromiseConstructor interface represents the constructor for the polyfill Promise object.
 * @since 0.5.0
 * @group Polyfill
 */
export declare interface PolyPromiseConstructor {
    /**
     * Creates a new Promise.
     * @constructor
     * @param executor - A callback used to initialize the promise. This callback is passed two arguments:
     * a resolve callback used to resolve the promise with a value or the result of another promise,
     * and a reject callback used to reject the promise with a provided reason or error.
     */
    new <T>(executor: PromiseExecutor<T>): IPromise<T>;
    /**
     * Returns a single asynchronous Promise instance that resolves to an array of the results from the input promises.
     * This returned promise will resolve and execute it's pending chained operations __asynchronously__ using the optional
     * provided timeout value to schedule when the chained items will be executed, or if the input contains no promises.
     * It rejects immediately upon any of the input promises rejected or non-promises throwing an error,
     * and will reject with this first rejection message / error.
     * When resolved or rejected any additional chained operations will execute __asynchronously__ using the optional
     * timeout value to schedul when the chained item will be executed (eg. `then()`; `catch()`; `finally()`).
     * @group Polyfill
     * @param input - The array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
     * @returns
     * <ul>
     * <li> An already resolved `Promise`, if the input passed is empty.
     * <li> A pending `Promise` in all other cases. This returned promise is then resolved/rejected __synchronously__
     * (as soon as the pending items is empty) when all the promises in the given input have resolved, or if any of the
     * promises reject.
     * </ul>
     */
    all<T>(input: Iterable<PromiseLike<T>>, timeout?: number): IPromise<T[]>;
    /**
     * The `createAsyncRacePromise` method takes an array of promises as input and returns a single Promise. This returned promise
     * settles with the eventual state of the first promise that settles.
     * @description The `createAsyncRacePromise` method is one of the promise concurrency methods. It's useful when you want the first
     * async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
     * If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race() will settle to
     * the first of these values found in the iterable.
     * @since 0.5.0
     * @group Polyfill
     * @param values - An iterable object of promises.
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
     * @returns A Promise that settles with the eventual state of the first promise in the iterable to settle. In other words, it fulfills if the
     * first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever
     * if the iterable passed is empty. If the iterable passed is non-empty but contains no pending promises, the returned promise is still
     * asynchronously settled.
     */
    race<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;
    /**
     * The `createAsyncRacePromise` method takes an array of promises as input and returns a single Promise. This returned promise
     * settles with the eventual state of the first promise that settles.
     * @description The `createAsyncRacePromise` method is one of the promise concurrency methods. It's useful when you want the first
     * async task to complete, but do not care about its eventual state (i.e. it can either succeed or fail).
     * If the iterable contains one or more non-promise values and/or an already settled promise, then Promise.race() will settle to
     * the first of these values found in the iterable.
     * @since 0.5.0
     * @group Polyfill
     * @param values - An iterable object of promises.
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
     * @returns A Promise that settles with the eventual state of the first promise in the iterable to settle. In other words, it fulfills if the
     * first promise to settle is fulfilled, and rejects if the first promise to settle is rejected. The returned promise remains pending forever
     * if the iterable passed is empty. If the iterable passed is non-empty but contains no pending promises, the returned promise is still
     * asynchronously settled.
     */
    race<T extends readonly unknown[] | []>(values: T, timeout?: number): IPromise<Awaited<T[number]>>;
    /**
     * The `createAsyncAnyPromise` method takes an iterable of promises as input and returns a single Promise.
     * This returned promise fulfills when any of the input's promises fulfills, with this first fulfillment value.
     * It rejects when all of the input's promises reject (including when an empty iterable is passed), with an
     * AggregateError containing an array of rejection reasons.
     * @since 0.5.0
     * @group Polyfill
     * @param values - An iterable object of promises.
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
     * @returns A new Promise that is:
     * - Already rejected, if the iterable passed is empty.
     * - Asynchronously fulfilled, when any of the promises in the given iterable fulfills. The fulfillment value
     * is the fulfillment value of the first promise that was fulfilled.
     * - Asynchronously rejected, when all of the promises in the given iterable reject. The rejection reason is
     * an AggregateError containing an array of rejection reasons in its errors property. The errors are in the
     * order of the promises passed, regardless of completion order. If the iterable passed is non-empty but
     * contains no pending promises, the returned promise is still asynchronously (instead of synchronously)
     * rejected.
     */
    any<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<Awaited<T>>;
    /**
     * The `createAsyncAnyPromise` method takes an iterable of promises as input and returns a single Promise.
     * This returned promise fulfills when any of the input's promises fulfills, with this first fulfillment value.
     * It rejects when all of the input's promises reject (including when an empty iterable is passed), with an
     * AggregateError containing an array of rejection reasons.
     * @since 0.5.0
     * @group Polyfill
     * @param values - An iterable object of promises.
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
     * @returns A new Promise that is:
     * - Already rejected, if the iterable passed is empty.
     * - Asynchronously fulfilled, when any of the promises in the given iterable fulfills. The fulfillment value
     * is the fulfillment value of the first promise that was fulfilled.
     * - Asynchronously rejected, when all of the promises in the given iterable reject. The rejection reason is
     * an AggregateError containing an array of rejection reasons in its errors property. The errors are in the
     * order of the promises passed, regardless of completion order. If the iterable passed is non-empty but
     * contains no pending promises, the returned promise is still asynchronously (instead of synchronously)
     * rejected.
     */
    any<T extends readonly unknown[] | []>(values: T, timeout?: number): IPromise<Awaited<T[number]>>;
    /**
     * Returns a single asynchronous Promise instance that is already rejected with the given reason.
     * Any chained operations will execute __asynchronously__ using the optional timeout value to schedule
     * when then chained items will be executed. (eg. `catch()`; `finally()`).
     * @group Polyfill
     * @param reason - The rejection reason
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
     * @returns A rejected promise.
     */
    reject<T = never>(reason?: any, timeout?: number): IPromise<T>;
    /**
     * Returns a single asynchronous Promise instance that is already resolved with the given value. If the value passed is
     * a promise then that promise is returned instead of creating a new asynchronous promise instance.
     * If a new instance is returned then any chained operations will execute __asynchronously__ using the optional
     * timeout value to schedule when the chained items will be executed.(eg. `then()`; `finally()`).
     * @group Polyfill
     * @returns A resolved promise.
     */
    resolve(): IPromise<void>;
    /**
     * Returns a single asynchronous Promise instance that is already resolved with the given value. If the value passed is
     * a promise then that promise is returned instead of creating a new asynchronous promise instance.
     * If a new instance is returned then any chained operations will execute __asynchronously__ using the optional
     * timeout value to schedule when the chained items will be executed.(eg. `then()`; `finally()`).
     * @group Polyfill
     * @param value - The value to be used by this `Promise`. Can also be a `Promise` or a thenable to resolve.
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero.
     * @returns A resolved promise.
     */
    resolve<T>(value: T | PromiseLike<T>, timeout?: number): IPromise<T>;
    /**
     * Returns a single Promise instance that resolves to an array of the results from the input promises.
     * This returned promise will resolve and execute it's pending chained operations based on the
     * {@link createAsyncPromise | Asynchronous} promise implementation. Any chained operations will execute
     * __asynchronously__  when the final operation pending promises have resolved, or if the input contains
     * no promises. It will resolve only after all of the input promises have either resolved or rejected,
     * and will resolve with an array of {@link IPromiseResult } objects that each describe the outcome of
     * each promise.
     * @since 0.5.0
     * @group Polyfill
     * @param values - An array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
     * @returns A pending `Promise` that will resolve to an array of {@link IPromiseResult } objects that each describe the outcome of each promise.
     */
    allSettled<T extends readonly unknown[] | []>(values: T, timeout?: number): IPromise<{
        -readonly [P in keyof T]: IPromiseResult<Awaited<T[P]>>;
    }>;
    /**
     * Returns a single Promise instance that resolves to an array of the results from the input promises.
     * This returned promise will resolve and execute it's pending chained operations based on the
     * {@link createAsyncPromise | Asynchronous} promise implementation. Any chained operations will execute
     * __asynchronously__  when the final operation pending promises have resolved, or if the input contains
     * no promises. It will resolve only after all of the input promises have either resolved or rejected,
     * and will resolve with an array of {@link IPromiseResult } objects that each describe the outcome of
     * each promise.
     * @since 0.5.0
     * @group Polyfill
     * @param values - An array of promises to wait to be resolved / rejected before resolving or rejecting the new promise
     * @param timeout - Optional timeout to wait before processing the items, defaults to zero, only used when Native promises are not available.
     * @returns A pending `Promise` that will resolve to an array of {@link IPromiseResult } objects that each describe the outcome of each promise.
     */
    allSettled<T>(values: Iterable<T | PromiseLike<T>>, timeout?: number): IPromise<IPromiseResult<Awaited<T>>[]>;
}

/**
 * Defines the signature of a function that creates a Promise.
 * @param newExecutor - The executor to run in the context of the promise
 * @param extraArgs - Any extra arguments that can be passed to the creator
 * @returns A Promise `IPromise` implemenetation
 */
export declare type PromiseCreatorFn = <T, TResult2 = never>(newExecutor: PromiseExecutor<T>, ...extraArgs: any) => IPromise<T | TResult2>;

/**
 * A function to be executed during the creation of a promise instance. It receives two functions as parameters: resolve and reject.
 * Any errors thrown in the executor will cause the promise to be rejected, and the return value will be neglected. The semantics of executor are detailed below.
 * @param resolve - The handler function that should be called when the operation has completed and the promise can continue.
 * @param reject - The handler function that should be called to cause the promise to be rejected.
 */
export declare type PromiseExecutor<T> = (resolve: ResolvePromiseHandler<T>, reject: RejectPromiseHandler) => void;

/**
 * This defines the handler function for when a promise is rejected.
 * @param value - This is the value passed as part of resolving the Promise
 * @return This may return a value, another Promise or void. @see {@link https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html#then | IPromise.then} for how the value is handled.
 */
export declare type RejectedPromiseHandler<T = never> = (((reason: any) => T | IPromise<T> | PromiseLike<T>) | undefined | null);

/**
 * Defines the signature of the reject function passed to the resolverFunc (in the Promise constructor)
 * @param reason - The reason to reject the Promise with
 * @returns Nothing
 */
export declare type RejectPromiseHandler = (reason?: any) => void;

/**
 * This defines the handler function for when a promise is resolved.
 * @param value - This is the value passed as part of resolving the Promise
 * @return This may return a value, another Promise or void. @see {@link https://nevware21.github.io/ts-async/typedoc/interfaces/IPromise.html#then | IPromise.then} for how the value is handled.
 */
export declare type ResolvedPromiseHandler<T, TResult1 = T> = (((value: T) => TResult1 | IPromise<TResult1> | PromiseLike<TResult1>) | undefined | null);

/**
 * Defines the signature of the resolve function passed to the resolverFunc (in the Promise constructor)
 * @param value - The value to resolve the Promise with
 * @returns Nothing
 */
export declare type ResolvePromiseHandler<T> = (value: T | IPromise<T> | PromiseLike<T>) => void;

/**
 * Set the default promise implementation to use when calling `createPromise`; `createAllPromise`; `createResolvedPromise`
 * and `createRejectedPromise`. This is effective a global value and changing this will affect ALL callers of these
 * functions, as such these functions should only be used when switching implementations would have not unexpected
 * consequences like switching from a `createSyncPromise` to `createIdlePromise` where idle promises have a possibility
 * of never getting called during application shutdown or during an expected timeframe.
 * @group Alias
 * @group Promise
 * @param creator - The creator function to call when a new promise is required.
 */
export declare function setCreatePromiseImpl(creator: <T>(executor: PromiseExecutor<T>, timeout?: number) => IPromise<T>): void;

/**
 * Sets the global default idle timeout / deadline to use when no timeout is passed during promise creation.
 * @param idleDeadline - Specifies the time in milliseconds to use as the idle timeout / deadline by when any
 * outstanding chained items should be executed.
 * @group Idle
 */
export declare function setDefaultIdlePromiseTimeout(idleDeadline?: number | undefined): void;

/**
 * @deprecated Use `setDefaultIdlePromiseTimeout` instead
 * Sets the global default idle timeout / deadline to use when no timeout is passed during promise creation.
 * @param idleDeadline - Specifies the time in milliseconds to use as the idle timeout / deadline by when any
 * outstanding chained items should be executed.
 *
 * @function
 * @group Idle
 */
export declare const setDefaultIdleTimeout: typeof setDefaultIdlePromiseTimeout;

/**
 * Debug helper to enable internal debugging of the promise implementations. Disabled by default.
 * For the generated packages included in the npm package the `logger` will not be called as the
 * `_debugLog` function that uses this logger is removed during packaging.
 *
 * It is available directly from the repository for unit testing.
 *
 * @group Debug
 * @param enabled - Should debugging be enabled (defaults `false`, when `true` promises will have
 * additional debug properties and the `toString` will include extra details.
 * @param logger - Optional logger that will log internal state changes, only called in debug
 * builds as the calling function is removed is the production artifacts.
 * @example
 * ```ts
 * // The Id is the id of the promise
 * // The message is the internal debug message
 * function promiseDebugLogger(id: string, message: string) {
 *     if (console && console.log) {
 *         console.log(id, message);
 *     }
 * }
 *
 * setPromiseDebugState(true, promiseDebugLogger);
 *
 * // While the logger will not be called for the production packages
 * // Setting the `enabled` flag to tru will cause each promise to have
 * // the following additional properties added
 * // [[PromiseState]]; => Same as the `state` property
 * // [[PromiseResult]]; => The settled value
 * // [[PromiseIsHandled]] => Identifies if the promise has been handled
 * // It will also cause the `toString` for the promise to include additional
 * // debugging information
 * ```
 */
export declare function setPromiseDebugState(enabled: boolean, logger?: (id: string, message: string) => void): void;

/**
 * Identifies the function to call to start and execute the task when its
 * ready to be executed.
 * @since 0.2.0
 * @group Scheduler
 * @param taskName - The optional task name that was assigned to this task, it is passed by the task scheduler.
 * @returns The result or a IPromise that will be resolved / rejected when the task
 * was completed.
 * @example
 * ```ts
 * function taskFunc1() {
 *     return 42;
 * }
 *
 * function taskFunc2(taskName: string) {
 *     console.log("Running Task: " + taskName);
 *     return fetch("https://example.com/xxxx").then((response) => {
 *         // ...
 *     });
 * }
 *
 * function taskFunc3() {
 *     return Promise.all([...]);
 * }
 *
 * function taskFunc4() {
 *     return createAllPromise([...]);
 * }
 *
 * function taskFunc5(taskName: string) {
 *     return createPromise(() => {
 *         scheduleTimeout(() => {
 *             console.log("Completing task: " + taskName);
 *             resolve(true);
 *         }, 100);
 *     });
 * }
 * ```
 */
export declare type StartQueuedTaskFn<T> = (taskName?: string) => T | IPromise<T>;

export { }
