import { channel, Synnax } from '@synnaxlabs/client';
import { Destructor, IsExactlyUndefined, observe, record } from '@synnaxlabs/x';
import { default as z } from 'zod';
import { state } from '../../state';
import { status } from '../../status/aether';
export interface SetHandler<Value, SetExtra extends unknown | undefined = undefined> {
    (value: Value, variant: SetExtra): void | Promise<void>;
}
export interface DeleteHandler<K extends record.Key> {
    (key: K): void | Promise<void>;
}
export declare class ScopedUnaryStore<Key extends record.Key = record.Key, Value extends state.State = state.State, SetExtra extends unknown | undefined = undefined> {
    private readonly entries;
    private readonly setListeners;
    private readonly deleteListeners;
    private readonly handleError;
    private readonly equal;
    constructor(handleError: status.ErrorHandler, equal?: (a: Value, b: Value, key: Key) => boolean);
    private setOne;
    /**
     * Sets a value for the given key in the store.
     *
     * @param key - The key to set
     * @param value - The value to set, or a function to compute the value from the previous state
     * @param opts - Options for the set operation
     * @returns A rollback function that undoes the set operation
     */
    set(scope: string, key: Key | Array<Value & record.Keyed<Key>> | (Value & record.Keyed<Key>), value?: state.SetArg<Value | undefined> | SetExtra, extra?: SetExtra): () => void;
    get(keys: Key | Key[] | ((value: Value) => boolean)): Value | Value[] | undefined;
    list(): Value[];
    has(key: Key | Key[]): boolean;
    /**
     * Deletes entries from the store and notifies delete listeners.
     * @param key - The key(s) to delete or a filter function
     * @param variant - Optional variant data for set operations during rollback
     * @returns A rollback function that restores the deleted entries
     */
    delete(scope: string, key: Key | Key[] | ((value: Value, key: Key) => boolean), variant?: SetExtra): () => void;
    clear(): void;
    /**
     * Registers a listener for set operations.
     *
     * @param callback - Function to call when a value is set
     * @param key - Optional key to filter notifications (if provided, only changes to this
     * key trigger the callback)
     * @returns A destructor function to remove the listener
     */
    onSet(scope: string, callback: SetHandler<Value, SetExtra>, key?: Key): Destructor;
    /**
     * Registers a listener for delete operations.
     *
     * @param callback - Function to call when a value is deleted
     * @param key - Optional key to filter notifications (if provided, only deletion
     * of this key triggers the callback)
     * @returns A destructor function to remove the listener
     */
    onDelete(scope: string, callback: observe.AsyncHandler<Key> | observe.Handler<Key>, key?: Key): Destructor;
    private notifySet;
    private notifyDelete;
    scope(scope: string): UnaryStore<Key, Value, SetExtra>;
}
/**
 * Configuration for listening to changes on a specific Synnax channel.
 *
 * @template ScopedStore - The type of the store available to the listener
 * @template Schema - Zod schema type for validating channel data
 */
export interface ChannelListener<ScopedStore extends Store = {}, Z extends z.ZodType = z.ZodType> {
    /** The name of the Synnax channel to listen to */
    channel: channel.Name;
    /** Zod schema for parsing and validating channel data */
    schema: Z;
    /** Callback function invoked when the channel data changes */
    onChange: (args: ChannelListenerArgs<ScopedStore, Z>) => Promise<unknown> | unknown;
}
/**
 * Arguments passed to a channel listener's onChange callback.
 *
 * @template ScopedStore - The type of the store available to the listener
 * @template Z - Zod schema type for validating channel data
 */
export type ChannelListenerArgs<ScopedStore extends Store = {}, Z extends z.ZodType = z.ZodType> = {
    /** The parsed and validated data that changed */
    changed: z.output<Z>;
    /** The Synnax client instance for making additional API calls */
    client: Synnax;
    /** The store instance available to the listener */
    store: ScopedStore;
};
/**
 * Configuration for a single UnaryStore including its channel listeners.
 *
 * @template ScopedStore - The type of the scoped store
 */
export interface UnaryStoreConfig<ScopedStore extends Store = {}, Key extends record.Key = record.Key, Value extends state.State = state.State> {
    /** Function to determine if two values are equal */
    equal?: (a: Value, b: Value, key: Key) => boolean;
    /** Array of channel listeners to register for this store */
    listeners: ChannelListener<ScopedStore>[];
}
/**
 * Configuration object for creating a store with multiple UnaryStore instances.
 * Keys are store names and values are their configurations.
 *
 * @template ScopedStore - The type of the scoped store
 */
export interface StoreConfig<ScopedStore extends Store = {}> {
    [key: string]: UnaryStoreConfig<ScopedStore, any, any>;
}
export type UnaryStore<Key extends record.Key = record.Key, Value extends state.State = state.State, SetExtra extends unknown | undefined = undefined> = {
    get(key: Key): Value | undefined;
    get(keys: Key[] | ((value: Value) => boolean)): Value[];
    list(): Value[];
    has(key: Key | Key[]): boolean;
    onSet(callback: SetHandler<Value, SetExtra>, key?: Key): Destructor;
    onDelete(callback: DeleteHandler<Key>, key?: Key): Destructor;
} & (IsExactlyUndefined<SetExtra> extends true ? {
    set(key: Key, value: state.SetArg<Value | undefined>): () => void;
    set(value: (Value & record.Keyed<Key>) | Array<Value & record.Keyed<Key>>): () => void;
    delete(key: Key | Key[] | ((value: Value, key: Key) => boolean)): () => void;
} : {
    set(key: Key, value: state.SetArg<Value | undefined>, variant: SetExtra): () => void;
    set(values: (Value & record.Keyed<Key>) | Array<Value & record.Keyed<Key>>, variant: SetExtra): () => void;
    delete(key: Key | Key[] | ((value: Value, key: Key) => boolean), variant?: SetExtra): () => void;
});
/**
 * Base interface for a collection of UnaryStore instances.
 * Each property is a UnaryStore with its own key-value type.
 */
export interface Store {
    [key: string]: UnaryStore<any, any, undefined> | UnaryStore<string, any, unknown>;
}
export interface InternalStore {
    [key: string]: ScopedUnaryStore<string, state.State, string>;
}
/**
 * Creates a new store instance from the provided configuration.
 * Each key in the config becomes a UnaryStore in the resulting store.
 *
 * @template ScopedStore - The type of the store to create
 * @param config - Configuration object defining the store structure
 * @returns A new store instance with UnaryStore instances for each config key
 */
export declare const createStore: <ScopedStore extends Store>(config: StoreConfig<ScopedStore>, handleError: status.ErrorHandler) => InternalStore;
export declare const scopeStore: <ScopedStore extends Store>(store: InternalStore, scope: string) => ScopedStore;
export declare const partialUpdate: <Key extends record.Key, Value extends Record<any, any>>(store: UnaryStore<Key, Value>, key: Key, value: Partial<Value>) => Destructor;
//# sourceMappingURL=store.d.ts.map