import { Synnax as Client } from '@synnaxlabs/client';
import { compare, CrudeTimeSpan, Destructor, MultiSeries, record } from '@synnaxlabs/x';
import { flux } from './aether';
import { FetchOptions, Params } from './core/params';
import { Result } from './result';
import { CreateRetrieveArgs, MountListenersArgs } from './retrieve';
import { state } from '../state';
/**
 * Function interface for getting items from a list by key(s).
 *
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
interface GetItem<K extends record.Key, E extends record.Keyed<K>> {
    /** Get a single item by key, returns undefined if not found */
    (key: K): E | undefined;
    /** Get multiple items by an array of keys */
    (keys: K[]): E[];
}
/**
 * Options for async list operations.
 */
interface AsyncListOptions extends FetchOptions {
    /**
     * How to modify the list when new data is retrieved. In append mode, new entries
     * will be added to the end of the list. In replace mode, the list will be replaced
     * with the new data.
     */
    mode?: "append" | "replace";
}
/**
 * Return type for the list hook, providing comprehensive list management utilities.
 *
 * @template RetrieveParams The type of parameters for the retrieve operation
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
export type UseListReturn<RetrieveParams extends Params, K extends record.Key, E extends record.Keyed<K>> = Omit<Result<K[]>, "data"> & {
    /** Function to trigger a list retrieval operation (fire-and-forget) */
    retrieve: (params: state.SetArg<RetrieveParams, Partial<RetrieveParams>>, options?: AsyncListOptions) => void;
    /** Function to trigger a list retrieval operation and await the result */
    retrieveAsync: (params: state.SetArg<RetrieveParams, Partial<RetrieveParams>>, options?: AsyncListOptions) => Promise<void>;
    /** Array of keys for the items currently in the list */
    data: K[];
    /** Function to get items by key, with automatic lazy loading */
    getItem: GetItem<K, E>;
    /** Function to subscribe to changes for specific items */
    subscribe: (callback: () => void, key: K) => Destructor;
};
/**
 * Arguments for retrieving a single item by key.
 *
 * @template RetrieveParams The type of parameters for the retrieve operation
 * @template K The type of the key (must be a record key)
 */
export interface RetrieveByKeyArgs<RetrieveParams extends Params, K extends record.Key, ScopedStore extends flux.Store> {
    /** Parameters for the retrieve operation */
    params: Partial<RetrieveParams>;
    /** The key of the item to retrieve */
    key: K;
    /** The Synnax client instance */
    client: Client;
    /** The store instance */
    store: ScopedStore;
}
export interface RetrieveCachedArgs<RetrieveParams extends Params, ScopedStore extends flux.Store> {
    params: Partial<RetrieveParams>;
    store: ScopedStore;
}
/**
 * Configuration arguments for creating a list query.
 *
 * @template RetrieveParams The type of parameters for the retrieve operation
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
export interface CreateListArgs<RetrieveParams extends Params, K extends record.Key, E extends record.Keyed<K>, ScopedStore extends flux.Store> extends Omit<CreateRetrieveArgs<RetrieveParams, E[], ScopedStore>, "mountListeners"> {
    /** Function to sort the list */
    sort?: compare.Comparator<E>;
    /** Function to retrieve a single item by key for lazy loading */
    retrieveByKey: (args: RetrieveByKeyArgs<RetrieveParams, K, ScopedStore>) => Promise<E | undefined>;
    /** Function that allows  */
    retrieveCached?: (args: RetrieveCachedArgs<RetrieveParams, ScopedStore>) => E[];
    /** Function to mount listeners for the list */
    mountListeners?: (args: ListMountListenersArgs<RetrieveParams, K, E, ScopedStore>) => Destructor | Destructor[];
}
/**
 * Arguments for using a list hook.
 *
 * @template RetrieveParams The type of parameters for the retrieve operation
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
export interface UseListArgs<RetrieveParams extends Params, K extends record.Key, E extends record.Keyed<K>> {
    /** Initial parameters for the list query */
    initialParams?: RetrieveParams;
    /** Optional filter function to apply to items */
    filter?: (item: E) => boolean;
    /** Optional function to sort the list */
    sort?: compare.Comparator<E>;
    /** Debounce time for retrieve operations */
    retrieveDebounce?: CrudeTimeSpan;
}
/**
 * List hook function signature.
 *
 * @template RetrieveParams The type of parameters for the retrieve operation
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
export interface UseList<RetrieveParams extends Params, K extends record.Key, E extends record.Keyed<K>> {
    (args?: UseListArgs<RetrieveParams, K, E>): UseListReturn<RetrieveParams, K, E>;
}
type ListChangeMode = "prepend" | "append" | "replace";
interface ListenerOnChangeOptions {
    mode?: ListChangeMode;
}
/**
 * Extra arguments passed to list listener handlers.
 *
 * @template RetrieveParams The type of parameters for the retrieve operation
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
export interface ListListenerExtraArgs<RetrieveParams extends Params, K extends record.Key, E extends record.Keyed<K>> {
    changed: MultiSeries;
    /** The current retrieve parameters */
    params: RetrieveParams;
    /** The Synnax client instance */
    client: Client;
    /** Function to update a specific item in the list */
    onChange: (key: K, e: state.SetArg<E | null>, opts?: ListenerOnChangeOptions) => void;
    /** Function to remove an item from the list */
    onDelete: (key: K) => void;
}
/**
 * Configuration for a list listener that handles real-time updates.
 *
 * @template RetrieveParams The type of parameters for the retrieve operation
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
export interface ListMountListenersArgs<RetrieveParams extends Params, K extends record.Key, E extends record.Keyed<K>, ScopedStore extends flux.Store> extends Omit<MountListenersArgs<ScopedStore, RetrieveParams, E[]>, "onChange" | "params"> {
    params: Partial<RetrieveParams>;
    onChange: (key: K, e: state.SetArg<E | null>, opts?: ListenerOnChangeOptions) => void;
    onDelete: (key: K) => void;
}
/**
 * Creates a list query hook that provides comprehensive list management with real-time updates.
 *
 * This function creates a React hook that handles:
 * - List data retrieval with loading states
 * - Individual item lazy loading
 * - Real-time synchronization with server state
 * - Pagination and infinite scrolling support
 * - Item filtering and search
 * - Optimistic updates and error handling
 * - Subscribe to individual item changes
 *
 * @template P The type of parameters for the list query
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 * @param config Configuration object with list retrieval functions and settings
 * @returns A React hook for managing the list
 *
 * @example
 * ```typescript
 * interface UserListParams extends Params {
 *   department?: string;
 *   searchTerm?: string;
 *   offset?: number;
 *   limit?: number;
 * }
 *
 * interface User {
 *   id: number;
 *   name: string;
 *   email: string;
 *   department: string;
 * }
 *
 * const useUserList = createList<UserListParams, number, User>({
 *   name: "users",
 *   retrieve: async ({ params, client }) => {
 *     return await client.users.list(params);
 *   },
 *   retrieveByKey: async ({ key, client }) => {
 *     return await client.users.get(key);
 *   },
 *   listeners: [
 *     {
 *       channel: "user_updates",
 *       onChange: ({ changed, onChange, onDelete }) => {
 *         const updates = changed.get("user_updates");
 *         updates.forEach(update => {
 *           if (update.deleted) {
 *             onDelete(update.id);
 *           } else {
 *             onChange(update.id, update);
 *           }
 *         });
 *       }
 *     }
 *   ]
 * });
 *
 * // Usage in component
 * const { data, getItem, retrieve, variant } = useUserList({
 *   initialParams: { department: "engineering" },
 *   filter: (user) => user.name.includes("John")
 * });
 *
 * // Get individual user (lazy loaded if not in cache)
 * const user = getItem(123);
 *
 * // Load more users
 * retrieve({ offset: data.length, limit: 10 }, { mode: "append" });
 * ```
 */
export declare const createList: <P extends Params, K extends record.Key, E extends record.Keyed<K>, ScopedStore extends flux.Store = {}>({ name, mountListeners, retrieve, retrieveByKey, retrieveCached, sort: defaultSort, }: CreateListArgs<P, K, E, ScopedStore>) => UseList<P, K, E>;
/**
 * Arguments for the useListItem hook.
 *
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 */
export interface UseListItemArgs<K extends record.Key, E extends record.Keyed<K>> extends Pick<UseListReturn<Params, K, E>, "subscribe" | "getItem"> {
    /** The key of the item to retrieve and subscribe to */
    key: K;
}
/**
 * Hook for subscribing to and retrieving individual items from a list.
 *
 * This hook provides a way to efficiently track individual items from a list
 * with automatic re-rendering when the item changes. It uses React's
 * useSyncExternalStore to provide optimal performance.
 *
 * @template K The type of the key (must be a record key)
 * @template E The type of the entity (must be keyed by K)
 * @param args Configuration object with key and list utilities
 * @returns The current item data, or undefined if not found
 *
 * @example
 * ```typescript
 * const userList = useUserList();
 * const user = useListItem({
 *   key: userId,
 *   subscribe: userList.subscribe,
 *   getItem: userList.getItem
 * });
 *
 * // Component will re-render when this specific user changes
 * if (user) {
 *   return <div>{user.name} - {user.email}</div>;
 * }
 * ```
 */
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