import { StateStore } from '../store';
import { type DebouncedFunc } from '../utils';
import type { QueryReturnValue, SearchSourceOptions, SearchSourceState, SearchSourceType } from './types';
/**
 * Passed to a search source's `query()`. Carries a cancellation handle and makes no
 * claim that the query performs a request: a source may resolve from local data and
 * ignore the signal. Where a source does issue requests, forward this straight through
 * as the request options.
 */
export type SearchQueryOptions = {
    /** Aborted once a newer query supersedes this one. */
    signal?: AbortSignal;
};
export type DebounceOptions = {
    /** Applies to both short and long queries unless overridden by the options below. */
    debounceMs?: number;
    shortQueryDebounceMs?: number;
    longQueryDebounceMs?: number;
    shortQueryMaxLength?: number;
};
interface ISearchSource<T = any> {
    activate(): void;
    canExecuteQuery(newSearchString?: string): boolean;
    deactivate(): void;
    readonly hasNext: boolean;
    readonly hasResults: boolean;
    readonly initialState: SearchSourceState<T>;
    readonly isActive: boolean;
    readonly isLoading: boolean;
    readonly items: T[] | undefined;
    readonly lastQueryError: Error | undefined;
    readonly next: string | undefined | null;
    readonly offset: number | undefined;
    resetState(): void;
    readonly searchQuery: string;
    readonly state: StateStore<SearchSourceState<T>>;
    readonly type: SearchSourceType;
}
export interface SearchSource<T = any> extends ISearchSource<T> {
    cancelScheduledQuery(): void;
    setDebounceOptions(options: DebounceOptions): void;
    search(text?: string): Promise<void> | undefined;
}
export interface SearchSourceSync<T = any> extends ISearchSource<T> {
    cancelScheduledQuery(): void;
    setDebounceOptions(options: DebounceOptions): void;
    search(text?: string): void;
}
declare abstract class BaseSearchSourceBase<T, R extends void | Promise<void>> implements ISearchSource<T> {
    state: StateStore<SearchSourceState<T>>;
    pageSize: number;
    protected allowEmptySearchString: boolean;
    protected resetOnNewSearchQuery: boolean;
    protected shortQueryDebounceMs: number;
    protected longQueryDebounceMs: number;
    protected shortQueryMaxLength: number;
    protected searchDebounced: DebouncedFunc<(searchString?: string) => R>;
    abstract readonly type: SearchSourceType;
    protected constructor(options?: SearchSourceOptions);
    abstract executeQuery(newSearchString?: string): R;
    setDebounceOptions: (options?: DebounceOptions) => void;
    /**
     * Short queries match too much and are slow server-side, so they get a longer debounce.
     * Resolved per call, which is what lets the interval switch as the user keeps typing.
     */
    protected getDebounceMs: (searchString?: string) => number;
    /**
     * A new search query preempts an in-flight one; pagination waits for it to finish
     * and needs a next page to fetch.
     */
    protected canDispatchQuery(hasNewSearchQuery: boolean): boolean;
    search: (searchQuery?: string) => R | undefined;
    get lastQueryError(): Error | undefined;
    get hasNext(): boolean;
    get hasResults(): boolean;
    get isActive(): boolean;
    get isLoading(): boolean;
    get initialState(): SearchSourceState<T>;
    get items(): T[] | undefined;
    get next(): string | null | undefined;
    get offset(): number | undefined;
    get searchQuery(): string;
    activate: () => void;
    deactivate: () => void;
    canExecuteQuery: (newSearchString?: string) => boolean;
    protected getStateBeforeFirstQuery(newSearchString: string): SearchSourceState<T>;
    protected getStateAfterQuery(stateUpdate: Partial<SearchSourceState<T>>, isFirstPage: boolean): SearchSourceState<T>;
    protected prepareStateForQuery(newSearchString?: string): {
        searchString: string;
        hasNewSearchQuery: boolean;
    };
    protected updatePaginationStateFromQuery(result: QueryReturnValue<T>): Partial<SearchSourceState<T>>;
    resetState(): void;
    resetStateAndActivate(): void;
}
export declare abstract class BaseSearchSource<T> extends BaseSearchSourceBase<T, Promise<void>> implements SearchSource<T> {
    /** Aborts the in-flight request, if any, once a newer query is dispatched. */
    protected queryAbortController: AbortController | null;
    protected abstract query(searchQuery: string, options?: SearchQueryOptions): Promise<QueryReturnValue<T>>;
    protected abstract filterQueryResults(items: T[]): T[] | Promise<T[]>;
    /** Aborts the in-flight request, if any. Returns true when one was aborted. */
    protected abortInFlightQuery(): boolean;
    resetState(): void;
    executeQuery(newSearchString?: string): Promise<void>;
    cancelScheduledQuery(): void;
}
export declare abstract class BaseSearchSourceSync<T> extends BaseSearchSourceBase<T, void> implements SearchSourceSync<T> {
    protected abstract query(searchQuery: string): QueryReturnValue<T>;
    protected abstract filterQueryResults(items: T[]): T[];
    executeQuery(newSearchString?: string): void;
    cancelScheduledQuery(): void;
}
export {};
