import { GatewayRateLimitedDispatchData, GatewayOpcodeRateLimitMetadataMap } from 'discord-api-types/v10';

/**
 * Represents a type that may or may not be a promise
 */
type Awaitable<Value> = PromiseLike<Value> | Value;

/**
 * Lazy is a wrapper around a value that is computed lazily. It is useful for
 * cases where the value is expensive to compute and the computation may not
 * be needed at all.
 *
 * @param cb - The callback to lazily evaluate
 * @typeParam Value - The type of the value
 * @example
 * ```ts
 * const value = lazy(() => computeExpensiveValue());
 * ```
 */
declare function lazy<Value>(cb: () => Value): () => Value;

/**
 * Options for creating a range
 */
interface RangeOptions {
    /**
     * The end of the range (exclusive)
     */
    end: number;
    /**
     * The start of the range (inclusive)
     */
    start: number;
    /**
     * The amount to increment by
     *
     * @defaultValue `1`
     */
    step?: number;
}
/**
 * A generator to yield numbers in a given range
 *
 * @remarks
 * This method is end-exclusive, for example the last number yielded by `range(5)` is 4. If you
 * prefer for the end to be included add 1 to the range or `end` option.
 * @param range - A number representing the range to yield (exclusive) or an object with start, end and step
 * @example
 * Basic range
 * ```ts
 * for (const number of range(5)) {
 *  console.log(number);
 * }
 * // Prints 0, 1, 2, 3, 4
 * ```
 * @example
 * Range with a step
 * ```ts
 * for (const number of range({ start: 3, end: 10, step: 2 })) {
 * 	console.log(number);
 * }
 * // Prints 3, 5, 7, 9
 * ```
 */
declare function range(range: RangeOptions | number): Generator<number, void, unknown>;

/**
 * Calculates the shard id for a given guild id.
 *
 * @param guildId - The guild id to calculate the shard id for
 * @param shardCount - The total number of shards
 */
declare function calculateShardId(guildId: string, shardCount: number): number;

declare function shouldUseGlobalFetchAndWebSocket(): boolean;

/**
 * Resolves the user agent appendix string for the current environment.
 */
declare function getUserAgentAppendix(): string;

/**
 * Polyfill for `Symbol.dispose` and `Symbol.asyncDispose` which is used as a part of
 * {@link https://github.com/tc39/proposal-explicit-resource-management}. Node versions below 18.x
 * don't have these symbols by default, so we need to polyfill them.
 */
declare function polyfillDispose(): void;

/**
 * Represents an object capable of representing itself as a JSON object
 *
 * @typeParam Value - The JSON type corresponding to {@link JSONEncodable.toJSON} outputs.
 */
interface JSONEncodable<Value> {
    /**
     * Transforms this object to its JSON format
     */
    toJSON(): Value;
}
/**
 * Indicates if an object is encodable or not.
 *
 * @param maybeEncodable - The object to check against
 */
declare function isJSONEncodable(maybeEncodable: unknown): maybeEncodable is JSONEncodable<unknown>;

/**
 * Represents a structure that can be checked against another
 * given structure for equality
 *
 * @typeParam Value - The type of object to compare the current object to
 */
interface Equatable<Value> {
    /**
     * Whether or not this is equal to another structure
     */
    equals(other: Value): boolean;
}
/**
 * Indicates if an object is equatable or not.
 *
 * @param maybeEquatable - The object to check against
 */
declare function isEquatable(maybeEquatable: unknown): maybeEquatable is Equatable<unknown>;

/**
 * Represents the error thrown when the gateway emits a `RATE_LIMITED` event after a certain request.
 */
declare class GatewayRateLimitError extends Error {
    /**
     * The data associated with the rate limit event
     */
    readonly data: GatewayRateLimitedDispatchData<keyof GatewayOpcodeRateLimitMetadataMap>;
    /**
     * The payload data that lead to this rate limit
     *
     * @privateRemarks
     * Too complicated to type properly here (i.e. extract the ['data']
     * of event payloads that have t = keyof GatewayOpcodeRateLimitMetadataMap)
     */
    readonly payload: unknown;
    readonly name: string;
    constructor(
    /**
     * The data associated with the rate limit event
     */
    data: GatewayRateLimitedDispatchData<keyof GatewayOpcodeRateLimitMetadataMap>, 
    /**
     * The payload data that lead to this rate limit
     *
     * @privateRemarks
     * Too complicated to type properly here (i.e. extract the ['data']
     * of event payloads that have t = keyof GatewayOpcodeRateLimitMetadataMap)
     */
    payload: unknown);
}

/**
 * The {@link https://github.com/discordjs/discord.js/blob/main/packages/util#readme | @discordjs/util} version
 * that you are currently using.
 *
 * @privateRemarks This needs to explicitly be `string` so it is not typed as a "const string" that gets injected by esbuild.
 */
declare const version: string;

export { type Awaitable, type Equatable, GatewayRateLimitError, type JSONEncodable, type RangeOptions, calculateShardId, getUserAgentAppendix, isEquatable, isJSONEncodable, lazy, polyfillDispose, range, shouldUseGlobalFetchAndWebSocket, version };
