import type { Ord } from "rambda";
import type { FieldPathByValue } from "react-hook-form";
import type { AsyncOrSync } from "ts-essentials";
import type { Split } from "ts-toolbelt/out/String/Split";
import type { Awaitable } from "./Awaitable";
import { cacheLists } from "./cacheLists";
import { cacheSkips } from "./cacheSkips";
import { cacheTails } from "./cacheTails";
import { chunkBys } from "./chunkBys";
import { chunkIfs } from "./chunkIfs";
import { chunkIntervals } from "./chunkIntervals";
import { chunks } from "./chunks";
import type { ChunkTransformer } from "./chunkTransforms";
import { confluences } from "./confluences";
import { convolves } from "./convolves";
import { debounces } from "./debounces";
import { flatMaps } from "./flatMaps";
import { flats } from "./flats";
import type { FlowSource } from "./FlowSource";
import { forEachs } from "./forEachs";
import { heads } from "./heads";
import { limits } from "./limits";
import { lines } from "./lines";
import { logs } from "./logs";
import { mapAddFields } from "./mapAddFields";
import { maps } from "./maps";
import { peeks } from "./peeks";
import { riffles } from "./riffles";
import { skips } from "./skips";
import { slices } from "./slices";
import type { SourcesType } from "./SourcesType";
import { matchAlls, matchs, replaceAlls, replaces } from "./strings";
import { tails } from "./tails";
import { terminates } from "./terminates";
import { throttles } from "./throttles";
import { uniqBys, uniqs } from "./uniqs";
import type { Unwinded } from "./Unwinded";
import { csvFormats, tsvFormats } from "./xsvStreams";
export type Reducer<S, T> = (state: S, x: T, i: number) => Awaitable<S>;
export type EmitReducer<S, T, R> = (state: S, x: T, i: number) => Awaitable<{
    next: S;
    emit: R;
}>;
export interface BaseFlow<T> {
    _type: T;
    readable: ReadableStream<T>;
    writable: WritableStream<T>;
    /** @deprecated use chunk */
    buffer(...args: Parameters<typeof chunks<T>>): sflow<T[]>;
    cacheSkip(...args: Parameters<typeof cacheSkips<T>>): sflow<T>;
    cacheList(...args: Parameters<typeof cacheLists<T>>): sflow<T>;
    cacheTail(...args: Parameters<typeof cacheTails<T>>): sflow<T>;
    chunk(...args: Parameters<typeof chunks<T>>): sflow<T[]>;
    /** inverse of flat, chunk all items */
    chunk(): sflow<T[]>;
    /** inverse of flat, chunk or buffer a length as array */
    chunk(...args: Parameters<typeof chunks<T>>): sflow<T[]>;
    /** group by (only affect on concat items)*/
    chunkBy(...args: Parameters<typeof chunkBys<T>>): sflow<T[]>;
    /** @see {@link chunkIfs} */
    chunkIf(...args: Parameters<typeof chunkIfs<T>>): sflow<T[]>;
    chunkTransforms<T>(options: {
        start?: ChunkTransformer<T>;
        transform?: ChunkTransformer<T>;
        flush?: ChunkTransformer<T>;
    }): sflow<T>;
    /** @see convolves */
    convolve(...args: Parameters<typeof convolves<T>>): sflow<T[]>;
    /** act as pipeThrough<T,T> */
    portal: {
        (): sflow<T>;
        (stream: TransformStream<T, T>): sflow<T>;
        (fn: (s: sflow<T>) => FlowSource<T>): sflow<T>;
    };
    /** act as pipeThrough, alias of by */
    through: {
        (): sflow<T>;
        (stream: TransformStream<T, T>): sflow<T>;
        <R>(fn: (s: sflow<T>) => FlowSource<R>): sflow<R>;
        <R>(stream: TransformStream<T, R>): sflow<R>;
    };
    /** act as pipeThrough, alias of through */
    by: {
        (): sflow<T>;
        (stream: TransformStream<T, T>): sflow<T>;
        <R>(fn: (s: sflow<T>) => AsyncOrSync<FlowSource<R>>): sflow<R>;
        <R>(stream: TransformStream<T, R>): sflow<R>;
    };
    /** act as pipeThrough, but lazy, only pull upstream when downstream pull */
    byLazy: {
        (stream: TransformStream<T, T>): sflow<T>;
        <R>(stream: TransformStream<T, R>): sflow<R>;
    };
    /** @deprecated use chunkInterval */
    interval(...args: Parameters<typeof chunkIntervals<T>>): sflow<T[]>;
    chunkInterval(...args: Parameters<typeof chunkIntervals<T>>): sflow<T[]>;
    debounce(...args: Parameters<typeof debounces<T>>): sflow<T>;
    filter(fn: (x: T, i: number) => Awaitable<any>): sflow<T>;
    filter(): sflow<NonNullable<T>>;
    flatMap<R>(...args: Parameters<typeof flatMaps<T, R>>): sflow<R>;
    /** @deprecated to join another stream, use merge instead  */
    join(fn: (s: WritableStream<T>) => void | any): sflow<T>;
    /** @deprecated to join another stream, use merge instead  */
    join(stream?: ReadableStream<T>): sflow<T>;
    merge(fn: (s: WritableStream<T>) => void | any): sflow<T>;
    merge(stream?: ReadableStream<T>): sflow<T>;
    concat(fn: (s: WritableStream<T>) => void | any): sflow<T>;
    concat(stream?: ReadableStream<T>): sflow<T>;
    limit(...args: Parameters<typeof limits<T>>): sflow<T>;
    head(...args: Parameters<typeof heads<T>>): sflow<T>;
    map<R>(...args: Parameters<typeof maps<T, R>>): sflow<R>;
    log(...args: Parameters<typeof logs<T>>): sflow<T>;
    peek(...args: Parameters<typeof peeks<T>>): sflow<T>;
    riffle(...args: Parameters<typeof riffles<T>>): sflow<T>;
    forEach(...args: Parameters<typeof forEachs<T>>): sflow<T>;
    pMap<R>(fn: (x: T, i: number) => Awaitable<R>): sflow<R>;
    pMap<R>(fn: (x: T, i: number) => Awaitable<R>, options?: {
        concurrency?: number;
    }): sflow<R>;
    asyncMap<R>(fn: (x: T, i: number) => Awaitable<R>): sflow<R>;
    asyncMap<R>(fn: (x: T, i: number) => Awaitable<R>, options?: {
        concurrency?: number;
    }): sflow<R>;
    reduce(fn: (state: T | undefined, x: T, i: number) => Awaitable<T>): sflow<T>;
    reduce(fn: Reducer<T, T>, initialState: T): sflow<T>;
    reduce<S>(fn: (state: S | undefined, x: T, i: number) => Awaitable<S>): sflow<S>;
    reduce<S>(fn: Reducer<S, T>, initialState: S): sflow<S>;
    reduceEmit(fn: EmitReducer<T, T, T>): sflow<T>;
    reduceEmit<R>(fn: EmitReducer<T, T, R>): sflow<R>;
    reduceEmit<S, R>(fn: EmitReducer<S, T, R>, state: S): sflow<R>;
    skip: (...args: Parameters<typeof skips<T>>) => sflow<T>;
    slice: (...args: Parameters<typeof slices<T>>) => sflow<T>;
    tail: (...args: Parameters<typeof tails<T>>) => sflow<T>;
    uniq: (...args: Parameters<typeof uniqs<T>>) => sflow<T>;
    uniqBy: <K>(...args: Parameters<typeof uniqBys<T, K>>) => sflow<T>;
    /** @deprecated use fork, forkTo */
    tees(fn: (s: sflow<T>) => void | any): sflow<T>;
    /** @deprecated use fork, forkTo */
    tees(stream: WritableStream<T>): sflow<T>;
    forkTo(fn: (s: sflow<T>) => void | any): sflow<T>;
    forkTo(stream: WritableStream<T>): sflow<T>;
    /**
     * fork
     */
    fork(): sflow<T>;
    throttle: (...args: Parameters<typeof throttles<T>>) => sflow<T>;
    abort(...args: Parameters<typeof terminates<T>>): sflow<T>;
    terminateSignal(...args: Parameters<typeof terminates<T>>): sflow<T>;
    preventAbort: () => sflow<T>;
    preventClose: () => sflow<T>;
    preventCancel: () => sflow<T>;
    onStart: (start: TransformerStartCallback<T>) => sflow<T>;
    onTransform: <R>(transform: TransformerTransformCallback<T, R>) => sflow<R>;
    onFlush: (flush: TransformerFlushCallback<T>) => sflow<T>;
    done: () => Promise<void>;
    end: (pipeTo?: WritableStream<T>) => Promise<void>;
    run: () => Promise<void>;
    /** alias of pipeTo */
    to: (pipeTo?: WritableStream<T>) => Promise<void>;
    toArray: () => Promise<T[]>;
    toEnd: () => Promise<void>;
    toNil: () => Promise<void>;
    /** Count stream items, and drop items */
    toCount: () => Promise<number>;
    /** Get first item from stream, and terminate stream */
    toFirst: () => Promise<T>;
    /** Get one item from stream
     * throws if more than 1 item is emitted
     * return undefined if no item returned
     * return the item
     */
    toExactlyOne: (options?: {
        required?: boolean;
    }) => Promise<T | undefined>;
    /** Get one item from stream
     * throws if more than 1 item is emitted
     * return undefined if no item returned
     * return the item
     * @deprecated use toExactlyOne
     */
    toOne: (options?: {
        required?: boolean;
    }) => Promise<T | undefined>;
    /** Get one item from stream
     * throws if more than 1 item is emitted
     * throws if no items emitted, (required defaults to false)
     * return the item
     */
    toAtLeastOne: (options?: {
        required?: boolean;
    }) => Promise<T>;
    /** Returns a promise that always give you latest value of the stream */
    /** Get last item from stream, ignore others */
    toLast: () => Promise<T>;
    toLog(...args: Parameters<typeof logs<T>>): Promise<void>;
}
type ArrayFlow<T> = T extends ReadonlyArray<any> ? {
    flat: (...args: Parameters<typeof flats<T>>) => sflow<T[number]>;
} : {};
type DictionaryFlow<T> = T extends Record<string, any> ? {
    unwind<K extends FieldPathByValue<T, ReadonlyArray<any>>>(key: K): sflow<Unwinded<T, K>>;
    mapAddField: <K extends string, R>(...args: Parameters<typeof mapAddFields<K, T, R>>) => sflow<Omit<T, K> & {
        [key in K]: R;
    }>;
} : {};
type StreamsFlow<T> = T extends ReadableStream<infer R> ? {
    /** @deprecated use confluencesByBreth */
    confluence(...args: Parameters<typeof confluences<R>>): sflow<R>;
    confluenceByZip(): sflow<R>;
    confluenceByConcat(): sflow<R>;
    confluenceByParallel(): sflow<R>;
    confluenceByAscend(ordFn: (x: R) => Ord): sflow<R>;
    confluenceByDescend(ordFn: (x: R) => Ord): sflow<R>;
} : {};
type TextFlow<T> = T extends string ? {
    join: (sep: string) => sflow<string>;
    lines: (...args: Parameters<typeof lines>) => sflow<ReturnType<typeof lines> extends TransformStream<any, infer R> ? R : never>;
    match: (...args: Parameters<typeof matchs>) => sflow<ReturnType<typeof matchs> extends TransformStream<any, infer R> ? R : never>;
    matchAll: (...args: Parameters<typeof matchAlls>) => sflow<ReturnType<typeof matchAlls> extends TransformStream<any, infer R> ? R : never>;
    replace: (...args: Parameters<typeof replaces>) => sflow<ReturnType<typeof replaces> extends TransformStream<any, infer R> ? R : never>;
    replaceAll: (...args: Parameters<typeof replaceAlls>) => sflow<ReturnType<typeof replaceAlls> extends TransformStream<any, infer R> ? R : never>;
} : {};
type XsvEncodeFlow<T> = T extends Record<string, any> ? {
    csvFormat: (...args: Parameters<typeof csvFormats>) => sflow<ReturnType<typeof csvFormats> extends TransformStream<any, infer R> ? R : never>;
    tsvFormat: (...args: Parameters<typeof tsvFormats>) => sflow<ReturnType<typeof tsvFormats> extends TransformStream<any, infer R> ? R : never>;
} : {};
type XsvDecodeFlow<T> = T extends string ? {
    csvParse<S extends string>(header: S): sflow<Record<Split<S, ",">[number], any>>;
    csvParse<S extends string[]>(header: S): sflow<Record<S[number], any>>;
    tsvParse<S extends string>(header: S): sflow<Record<Split<S, ",">[number], any>>;
    tsvParse<S extends string[]>(header: S): sflow<Record<S[number], any>>;
} : {};
type ToResponse<T> = T extends string | Uint8Array ? {
    toResponse: () => Response;
    text: () => Promise<string>;
    json: () => Promise<any>;
    blob: () => Promise<Blob>;
    arrayBuffer: () => Promise<ArrayBuffer>;
} : {};
export type sflowType<T extends sflow<any>> = T extends sflow<infer R> ? R : never;
export type sflow<T> = ReadableStream<T> & AsyncIterableIterator<T> & BaseFlow<T> & ArrayFlow<T> & DictionaryFlow<T> & StreamsFlow<T> & TextFlow<T> & XsvEncodeFlow<T> & XsvDecodeFlow<T> & ToResponse<T>;
/** stream flow */
export declare function sflow<T0, SRCS extends FlowSource<T0>[] = FlowSource<T0>[]>(...srcs: SRCS): sflow<SourcesType<SRCS>>;
export declare const _tees: {
    <T>(fn: (s: sflow<T>) => void | any): TransformStream<T, T>;
    <T>(stream?: WritableStream<T>): TransformStream<T, T>;
};
export declare const _throughs: {
    <T>(stream?: TransformStream<T, T>): TransformStream<T, T>;
    <T, R>(stream: TransformStream<T, R>): TransformStream<T, R>;
    <T, R>(fn: (s: sflow<T>) => FlowSource<R>): TransformStream<T, R>;
};
export declare function _byLazy<T, R>(r: ReadableStream<T>, t: TransformStream<T, R>): sflow<R>;
export {};
