import { ActionChain, Observable, Settable } from '@zedux/core';
import { AtomApi } from '../classes/AtomApi.js';
import { Ecosystem } from '../classes/Ecosystem.js';
import { SelectorCache } from '../classes/Selectors.js';
import { AnyAtomInstance, AnyAtomTemplate, AtomGenerics, AtomGenericsToAtomApiGenerics, AtomInstanceType, AtomParamsType, AtomStateType } from './atoms.js';
export * from './atoms.js';
export declare type AnyNonNullishValue = {};
export interface AtomConfig<State = any> {
    dehydrate?: (state: State) => any;
    flags?: string[];
    hydrate?: (dehydratedState: unknown) => State;
    manualHydration?: boolean;
    ttl?: number;
}
/**
 * The AtomGettersBase interface. You probably won't want to use this directly.
 * Use AtomGetters instead.
 */
export interface AtomGettersBase {
    /**
     * Registers a dynamic graph edge on the resolved atom instance when called
     * synchronously during atom or AtomSelector evaluation. When called
     * asynchronously, is just an alias for `ecosystem.get`
     */
    get<A extends AnyAtomTemplate>(template: A, params: AtomParamsType<A>): AtomStateType<A>;
    get<A extends AnyAtomTemplate<{
        Params: [];
    }>>(template: A): AtomStateType<A>;
    get<A extends AnyAtomTemplate>(template: ParamlessTemplate<A>): AtomStateType<A>;
    get<I extends AnyAtomInstance>(instance: I): AtomStateType<I>;
    /**
     * Registers a static graph edge on the resolved atom instance when called
     * synchronously during atom or AtomSelector evaluation. When called
     * asynchronously, is just an alias for `ecosystem.getInstance`
     */
    getInstance<A extends AnyAtomTemplate>(template: A, params: AtomParamsType<A>, edgeInfo?: GraphEdgeInfo): AtomInstanceType<A>;
    getInstance<A extends AnyAtomTemplate<{
        Params: [];
    }>>(template: A): AtomInstanceType<A>;
    getInstance<A extends AnyAtomTemplate>(template: ParamlessTemplate<A>): AtomInstanceType<A>;
    getInstance<I extends AnyAtomInstance>(instance: I, params?: [], edgeInfo?: GraphEdgeInfo): I;
    /**
     * Runs an AtomSelector which receives its own AtomGetters object and can use
     * those to register its own dynamic and/or static graph edges (when called
     * synchronously during the AtomSelector's evaluation)
     *
     * ```ts
     * const mySelector = ion('mySelector', ({ select }) => {
     *   // registers a dynamic dependency on myAtom:
     *   const dynamicVal = select(({ get }) => get(myAtom))
     *
     *   injectEffect(() => {
     *     // doesn't register anything:
     *     const staticVal = select(({ get }) => get(myAtom))
     *   }, []) // no need to pass select as a dep; it's a stable reference
     * })
     * ```
     *
     * @see AtomSelector
     */
    select<T, Args extends any[]>(selectorOrConfigOrCache: Selectable<T, Args>, ...args: Args): T;
}
/**
 * AtomGetters are used all throughout Zedux. When called synchronously during
 * atom or AtomSelector evaluation, they register graph edges. When called
 * asynchronously, they're just aliases for the corresponding ecosystem method.
 *
 * ```ts
 * const mySelector = ion('mySelector', ({ ecosystem, get }) => {
 *   const dynamicVal = get(myAtom) // registers graph edge
 *   const staticVal = ecosystem.get(myAtom) // doesn't register anything
 *
 *   injectEffect(() => {
 *     const staticVal2 = get(myAtom) // doesn't register anything
 *     // const staticVal2 = ecosystem.get(myAtom) // same exact thing
 *   }, [])
 * })
 * ```
 */
export interface AtomGetters extends AtomGettersBase {
    /**
     * A reference to the ecosystem of the current atom instance or AtomSelector.
     *
     * The ecosystem itself has `get`, `getInstance`, and `select` methods which
     * can be used instead of the other AtomGetters to prevent graph dependencies
     * from being registered.
     *
     * ```ts
     * // the current component will NOT rerender when myAtom changes:
     * const staticVal = useAtomSelector(({ ecosystem }) => ecosystem.get(myAtom))
     *
     * // the current component will rerender when myAtom changes:
     * const dynamicVal = useAtomSelector(({ get }) => get(myAtom))
     * ```
     */
    ecosystem: Ecosystem;
}
export declare type AtomInstanceTtl = number | Promise<any> | Observable<any>;
export declare type AtomSelector<T = any, Args extends any[] = []> = (getters: AtomGetters, ...args: Args) => T;
export interface AtomSelectorConfig<T = any, Args extends any[] = []> {
    argsComparator?: (newArgs: Args, oldArgs: Args) => boolean;
    name?: string;
    resultsComparator?: (newResult: T, oldResult: T) => boolean;
    selector: AtomSelector<T, Args>;
}
export declare type AtomSelectorOrConfig<T = any, Args extends any[] = []> = AtomSelector<T, Args> | AtomSelectorConfig<T, Args>;
export declare type AtomStateFactory<G extends AtomGenerics> = (...params: G['Params']) => AtomApi<AtomGenericsToAtomApiGenerics<G>> | G['Store'] | G['State'];
export declare type AtomTuple<A extends AnyAtomTemplate> = [A, AtomParamsType<A>];
export declare type AtomValueOrFactory<G extends AtomGenerics> = AtomStateFactory<G> | G['Store'] | G['State'];
export declare type Cleanup = () => void;
export declare type DependentCallback = (signal: GraphEdgeSignal, val?: any, reason?: EvaluationReason) => any;
export interface DependentEdge {
    callback?: DependentCallback;
    createdAt: number;
    dependentKey?: string;
    flags: number;
    isMaterialized?: boolean;
    operation: string;
    prevEdge?: WeakRef<DependentEdge>;
    task?: () => void;
}
export interface EcosystemConfig<Context extends Record<string, any> | undefined = any> {
    atomDefaults?: {
        ttl?: number;
    };
    complexParams?: boolean;
    context?: Context;
    destroyOnUnmount?: boolean;
    flags?: string[];
    id?: string;
    onReady?: (ecosystem: Ecosystem<Context>, prevContext?: Context) => MaybeCleanup;
    overrides?: AnyAtomTemplate[];
    ssr?: boolean;
}
export interface EcosystemGraphNode {
    dependencies: Map<string, true>;
    dependents: Map<string, DependentEdge>;
    isSelector?: boolean;
    refCount: number;
    weight: number;
}
export declare type EffectCallback = () => MaybeCleanup | Promise<any>;
export interface EvaluationReason<State = any> {
    action?: ActionChain;
    newState?: State;
    oldState?: State;
    operation: string;
    sourceType: EvaluationSourceType;
    sourceId?: string;
    reasons?: EvaluationReason[];
    type: EvaluationType;
}
export declare type EvaluationSourceType = 'Atom' | 'AtomSelector' | 'External' | 'Injector' | 'Store';
export declare type EvaluationType = 'cache invalidated' | 'node destroyed' | 'promise changed' | 'state changed';
export declare type ExportsInfusedSetter<State, Exports> = Exports & {
    (settable: Settable<State>, meta?: any): State;
};
export declare type GraphEdgeInfo = [
    flags: number,
    operation: string
];
/**
 * A low-level detail that tells dependents what sort of event is causing the
 * current update. Promise changes and state updates are lumped together as
 * 'Update' signals. If you need to distinguish between them, look at the
 * EvaluationType (the `type` field) in the full reasons list.
 */
export declare type GraphEdgeSignal = 'Destroyed' | 'Updated';
export interface GraphViewRecursive {
    [key: string]: GraphViewRecursive;
}
export interface InjectAtomInstanceConfig {
    operation?: string;
    subscribe?: boolean;
}
export declare type InjectorDeps = any[] | undefined;
export declare type InjectOrUseSelector<State, Params extends any[]> = Params extends [] ? <D = any>(selector: (state: State) => D) => D : <D = any>(params: Params, selector: (state: State) => D) => D;
export interface InjectPromiseConfig<T = any> {
    dataOnly?: boolean;
    initialState?: T;
    runOnInvalidate?: boolean;
}
export interface InjectStoreConfig {
    hydrate?: boolean;
    subscribe?: boolean;
}
export declare type IonStateFactory<G extends AtomGenerics> = (getters: AtomGetters, ...params: G['Params']) => AtomApi<AtomGenericsToAtomApiGenerics<G>> | G['Store'] | G['State'];
export declare type LifecycleStatus = 'Active' | 'Destroyed' | 'Initializing' | 'Stale';
export declare type MaybeCleanup = Cleanup | void;
export interface MutableRefObject<T = any> {
    current: T;
}
/**
 * Many Zedux APIs make the `params` parameter optional if the atom doesn't take
 * params or has only optional params.
 */
export declare type ParamlessTemplate<A extends AnyAtomTemplate> = AtomParamsType<A> extends [AnyNonNullishValue | undefined | null, ...any[]] ? never : A;
/**
 * Part of the atom instance can be accessed during initial evaluation. The only
 * fields that are inaccessible are those that don't exist yet 'cause the
 * initial evaluation is supposed to create them.
 */
export declare type PartialAtomInstance = Omit<AnyAtomInstance, 'api' | 'exports' | 'promise' | 'store'>;
export declare type Prettify<T> = {
    [K in keyof T]: T[K];
} & AnyNonNullishValue;
export interface PromiseState<T> {
    data?: T;
    error?: Error;
    isError: boolean;
    isLoading: boolean;
    isSuccess: boolean;
    status: PromiseStatus;
}
export declare type PromiseStatus = 'error' | 'loading' | 'success';
export declare type Ref<T = any> = MutableRefObject<T>;
export interface RefObject<T = any> {
    readonly current: T | null;
}
export declare type Selectable<T = any, Args extends any[] = []> = AtomSelector<T, Args> | AtomSelectorConfig<T, Args> | SelectorCache<T, Args>;
export declare type StateHookTuple<State, Exports> = [
    State,
    ExportsInfusedSetter<State, Exports>
];
