import type { OrderAssurable } from './assure-order-types';
import type { FluentIterableEmitter } from './emitter';
import type TypedEmitter from 'typed-emitter';
import type { Predicate as FunctionPredicate, AsyncPredicate as AsyncFunctionPredicate, AnyIterable } from 'augmentative-iterable';
export declare const head: unique symbol;
export declare const tail: unique symbol;
export type AnyHack<T> = T extends never ? 'A' : 'B';
/**
 * Returns true wether T is any or unknown
 */
export type IsAnyOrUnknown<T> = unknown extends T ? true : AnyHack<T> extends 'A' ? false : AnyHack<T> extends 'B' ? false : true;
/**
 * Represents the first string or non iterable item from chained iterables
 */
export type ItemOrSelfType<T> = T extends string ? T : T extends Iterable<infer R> ? ItemOrSelfType<R> : T;
/**
 * Represents the type of the item of an iterable
 */
export type ItemType<T> = T extends Iterable<infer R> ? R : never;
/**
 * Represents the first string or non iterable item from chained iterables
 */
export type AsyncItemOrSelfType<T> = T extends string ? T : T extends AnyIterable<infer R> ? AsyncItemOrSelfType<R> : T;
/**
 * Represents the type of the item of an iterable or an async iterable
 */
export type AsyncItemType<T> = T extends AnyIterable<infer R> ? R : never;
/**
 * represent the options that can be used with fluentEmit
 */
export interface FluentEmitOptions {
    /**
     * The event which yields a new iterable item. Default 'data'
     */
    event?: string;
    /**
     * The event which throws an error. Default 'error'
     */
    error?: string;
    /**
     * The list of events which ends the iterable. Default ['end', 'close']
     */
    end?: string[];
    /**
     * The timeout for event awaiting. If specified, an error will be thrown when no event is emitted
     * before the deadline
     */
    timeout?: number;
}
export interface ErrorCallback {
    (error: Error, index: number): unknown;
}
export type Predicate<T> = FunctionPredicate<T> | keyof T;
export type AsyncPredicate<T> = AsyncFunctionPredicate<T> | keyof T;
/**
 * Represents a reducer of type `T` into the accumulator type `A`.<br>
 *   Example: `const sumReducer: Reducer<number, number> = (sum, next) => sum + next;`
 * @typeparam T The source type.
 * @typeparam A The accumulator type.
 */
export interface Reducer<T, A> {
    /**
     * Generates the next accumulator item based on the previous one and the next item under reduce.
     * @param current The previous accumulator value.
     * @param next The next item.
     * @returns The new accumulator value.
     */
    (current: A, next: T): A;
}
/**
 * Represents a reducer of type `T` into the accumulator type `A`.<br>
 *   Example: `const sumReducer: Reducer<number, number> = (sum, next) => sum + next;`
 * @typeparam T The source type.
 * @typeparam A The accumulator type.
 */
export interface AnyReducer<T, A> {
    /**
     * Generates the next accumulator item based on the previous one and the next item under reduce.
     * @param current The previous accumulator value.
     * @param next The next item.
     * @returns The new accumulator value.
     */
    (current: A, next: T): Promise<A> | A;
}
/**
 * Represents an asynchronous reducer of type `T` into the accumulator type `A`.<br>
 *   Example: `const sumReducer: AsyncReducer<Channel, number> = async (sum, next) => sum + await getNumberOfMessages(next)`
 * @typeparam T The source type.
 * @typeparam A The accumulator type.
 */
export interface AsyncReducer<T, A> {
    /**
     * Asynchronously generates the next accumulator item based on the previous one and the next item under reduce.
     * @param current The previous accumulator value.
     * @param next The next item.
     * @returns A promise of the new accumulator value.
     */
    (current: A, next: T): Promise<A> | A;
}
/**
 * Compares two instances of type `T`.<br>
 *   Example: `const levelComparer: Comparer<User> = (userA, userB) => userA.level - userB.level;`
 * @typeparam T The type of the compared instances.
 */
export interface Comparer<T> {
    /**
     * Compares `a` and `b`.
     * @param a The first instance (the left hand side of the comparison).
     * @param b The second instance (the right hand side of the comparison).
     * @returns A number which represents the result of the comparison. If **negative**, `a` precedes `b`, if **positive**, `b` precedes `a`, if **zero**, `a` equals to `b` in the comparison.
     */
    (a: T, b: T): number;
}
/**
 * Represents an action on an item of type `T`.<br>
 *   Example: ``const logUserAction: Action<User> = user => console.log(`User ${user.name} (id: ${user.id})`);``
 * @typeparam T The type of the item the action is defined on.
 */
export interface Action<T> {
    /**
     * Specifies the action to perform on `item`.
     * @param item The item the action is performed against.
     */
    (item: T): void;
}
/**
 * Represents an asynchronous action on an item of type `T`.<br>
 *   Example: `const createUserAction: AsyncAction<User> = async user => await database.put(user);`
 * @typeparam T The type of the item the action is defined on.
 */
export interface AsyncAction<T> {
    /**
     * Specifies the asynchronous action to perform on `item`.
     * @param item The item the action is performed against.
     * @returns The promise of any action.
     */
    (item: T): Promise<unknown> | unknown;
}
/**
 * Represents a group of items of type `T` with a key of type `R`.
 * @typeparam T The type of the items in the [[Group]].
 * @typeparam R The type of the key of the [[Group]].
 */
export interface Group<T, R> {
    /**
     * The key of the [[Group]].
     */
    key: R;
    /**
     * The items in the [[Group]].
     */
    values: Iterable<T>;
}
/**
 * Represents an indexed value of type `T`.
 * @typeparam T The type of the value the index is associated to.
 */
export interface Indexed<T> {
    /**
     * The index of the value.
     */
    idx: number;
    /**
     * The value.
     */
    value: T;
}
/**
 * A structure to controls the calculation of iterative means
 */
export interface AverageStepper {
    /**
     * Return the current avg/mean
     */
    readonly avg: number;
    /**
     * Return total number of computed items
     */
    readonly count: number;
    /**
     * Calculates next avg
     * @param y the next number to be considered
     */
    step(y: number): number;
}
export interface Equality<T> {
    (a: T, b: T): boolean;
}
export interface FluentEvents<T> {
    data(t: T): void;
    error(error: any): void;
    end(): void;
}
/**
 * Represents a page of a paginated resource.
 * @typeparam T The type of the elements of the page.
 * @typeparam TToken The type of the next page token associated to the page.
 */
export interface Page<T, TToken> {
    /**
     * The elements of the page.
     */
    results: T[];
    /**
     * The next page token associated to the page.
     */
    nextPageToken?: TToken;
}
/**
 * Represents a pager - responsible to retrieve pages from a paginated resource.
 * @typeparam T The type of the elements of the page.
 * @typeparam TToken The type of the next page token associated to the page.
 */
export interface Pager<T, TToken> {
    /**
     * Retrieves a page from a paginated resource.
     * @param nextPageToken The token represents the page to retrieve or the first page if undefined.
     * @returns A promise of the page requested.
     */
    (nextPageToken?: TToken): Promise<Page<T, TToken> | undefined>;
}
export interface FluentEmitter<T> extends TypedEmitter<FluentEvents<T>> {
}
export interface KVGroupTransform<K, V, NewV = V> {
    (key: K, value: V, previous: NewV[]): Iterable<NewV> | undefined;
}
export interface AsyncKVGroupTransform<K, V, NewV = V> {
    (key: K, value: V, previous: NewV[]): AnyIterable<NewV> | undefined;
}
/**
 * Represents a group of [[fluent]] items of type `T` with a key of type `R`.
 * @typeparam T The type of the items in the [[FluentGroup]].
 * @typeparam R The type of the key of the [[FluentGroup]].
 */
export interface FluentGroup<T, R> extends Group<T, R> {
    /**
     * The [[fluent]] items in the [[FluentGroup]].
     */
    values: FluentIterable<T>;
}
export type ToObjectKeyType<T, R1 extends keyof T> = T[R1] extends string | number | symbol ? T[R1] : any;
/**
 * Represents an iterable extended with common processing and mutating capabilities.<br>
 *   The capabilities introduced are defined as a [fluent interface](https://en.wikipedia.org/wiki/Fluent_interface) and thus they support *method chaining*.
 * @typeparam T The type of the items in the iterable.
 */
export interface FluentIterable<T> extends Iterable<T>, OrderAssurable<FluentIterable<T>>, FluentIterableEmitter<T> {
}
/**
 * Represents an asynchronous iterable extended with common processing and mutating capabilities.<br>
 *   The capabilities introduced are defined as a [fluent interface](https://en.wikipedia.org/wiki/Fluent_interface) and thus they support *method chaining*.
 * @typeparam T The type of the items in the asynchronous iterable.
 */
export interface FluentAsyncIterable<T> extends AsyncIterable<T>, OrderAssurable<FluentAsyncIterable<T>>, FluentIterableEmitter<T> {
}
export type KeysOfType<T, V> = {
    [K in keyof T]-?: T[K] extends V ? K : never;
}[keyof T];
