import { compare, CrudeTimeSpan, Destructor, record } from '@synnaxlabs/x';
import { flux } from './aether';
import { core } from './core';
import { Result } from './result';
import { CreateRetrieveParams, RetrieveMountListenersParams, RetrieveParams } from './retrieve';
import { state } from '../state';
export interface GetItem<K extends record.Key, E extends record.Keyed<K>> {
    (key: K): E | undefined;
    (keys: K[]): E[];
}
export interface AsyncListOptions extends core.FetchOptions {
    mode?: "append" | "replace";
}
export type UseListReturn<Query extends core.Shape, K extends record.Key, E extends record.Keyed<K>> = Omit<Result<K[]>, "data"> & {
    retrieve: (query: state.SetArg<Query, Partial<Query>>, options?: AsyncListOptions) => void;
    retrieveAsync: (query: state.SetArg<Query, Partial<Query>>, options?: AsyncListOptions) => Promise<void>;
    data: K[];
    getItem: GetItem<K, E>;
    subscribe: (callback: () => void, key: K) => Destructor;
};
export interface RetrieveByKeyParams<Query extends core.Shape, K extends record.Key, Store extends flux.Store> extends Omit<RetrieveParams<Query, Store>, "query"> {
    query: Partial<Query>;
    key: K;
}
export interface RetrieveCachedParams<Query extends core.Shape, Store extends flux.Store> {
    query: Partial<Query>;
    store: Store;
}
export interface CreateListParams<Query extends core.Shape, K extends record.Key, E extends record.Keyed<K>, Store extends flux.Store> extends Omit<CreateRetrieveParams<Query, E[], Store>, "mountListeners"> {
    sort?: compare.Comparator<E>;
    retrieveByKey: (args: RetrieveByKeyParams<Query, K, Store>) => Promise<E | undefined>;
    retrieveCached?: (args: RetrieveCachedParams<Query, Store>) => E[];
    mountListeners?: (args: ListMountListenersParams<Query, K, E, Store>) => Destructor | Destructor[];
}
export interface UseListParams<Query extends core.Shape, K extends record.Key, E extends record.Keyed<K>> {
    initialQuery?: Query;
    filter?: (item: E) => boolean;
    sort?: compare.Comparator<E>;
    retrieveDebounce?: CrudeTimeSpan;
    useCachedList?: boolean;
}
export interface UseList<Query extends core.Shape, K extends record.Key, E extends record.Keyed<K>> {
    (args?: UseListParams<Query, K, E>): UseListReturn<Query, K, E>;
}
type ListChangeMode = "prepend" | "append" | "replace";
interface ListenerOnChangeOptions {
    mode?: ListChangeMode;
}
interface OnListChange<K extends record.Key, E extends record.Keyed<K>> {
    (key: K, e: state.SetArg<E | null>, opts?: ListenerOnChangeOptions): void;
    (e: E, opts?: ListenerOnChangeOptions): void;
}
export interface ListMountListenersParams<Query extends core.Shape, Key extends record.Key, Data extends record.Keyed<Key>, Store extends flux.Store> extends Omit<RetrieveMountListenersParams<Query, Data[], Store>, "onChange" | "query"> {
    query: Partial<Query>;
    onChange: OnListChange<Key, Data>;
    onDelete: (key: Key) => void;
}
export declare const createList: <Query extends core.Shape, Key extends record.Key, Data extends record.Keyed<Key>, ScopedStore extends flux.Store = {}>({ name, mountListeners, retrieve, retrieveByKey, retrieveCached, sort: defaultSort, }: CreateListParams<Query, Key, Data, ScopedStore>) => UseList<Query, Key, Data>;
export interface UseListItemArgs<K extends record.Key, E extends record.Keyed<K>> extends Pick<UseListReturn<core.Shape, K, E>, "subscribe" | "getItem"> {
    key: K;
}
export declare const useListItem: <K extends record.Key, E extends record.Keyed<K>>({ key, subscribe, getItem, }: UseListItemArgs<K, E>) => E | undefined;
export {};
//# sourceMappingURL=list.d.ts.map