/**
 * A function that customizes equality check between a previous and new value
 */
export type IsEqual = (oldValue: unknown, newValue: unknown) => boolean;
/**
 * Atom is a stripped down version of a reactive signal. It is not
 * associated with any value - instead, it may be reported to be observed (i.e. read),
 * hence adding itself to the computed atoms and reactions as a dependency, or
 * or reported to be changed, thereby potentially triggering recalculation of
 * computed atoms and reactions that depend on it
 */
export type Atom = {
    reportObserved: () => boolean;
    reportChanged: () => void;
};
/**
 * Options for configuring the behavior of an {@link Atom}.
 * This includes listeners for when the atom becomes observed or unobserved.
 */
export type AtomOptions = {
    /**
     * A listener callback that gets called when the atom becomes observed, i.e. when
     * it is first read by a reaction or by a computed atom that is obsserved by at least
     * one reaction
     */
    onBecomeObservedListener?: () => void;
    /**
     * A listener callback that gets called when the atom stops being observed, i.e. when
     * all reactions that depend on it were stopped, or if none of those reaction
     * depend on it anymore
     */
    onBecomeUnobservedListener?: () => void;
};
/**
 * Represents a reactive value derived from other reactive sources.
 * Its value is cached and recomputed only when its dependencies change,
 * provided it's actively observed by a reaction.
 */
export type ComputedAtom<T> = {
    /**
     * A function that either returns a cached computed reactive atom value or
     * calculates the value of the atom and caches it until its dependencies change.
     * If the computed atom does not have any reactions that ultimately depend on it,
     * does not behave reactively like that - instead, it behaves like a getter that
     * always calculates the value upon getting it
     */
    get: () => T;
};
/**
 * Options for configuring reactive values, primarily concerning equality checks.
 */
export type ReactiveValueOptions = {
    equals?: IsEqual;
};
/**
 * Options for configuring computed values, primarily concerning equality checks.
 */
export type ComputedOptions = {
    equals?: IsEqual;
};
/**
 * Options for configuring a {@link ComputedAtom}.
 * Combines {@link ComputedOptions} for value comparison and {@link AtomOptions} for lifecycle events.
 */
export type ComputedAtomOptions = ComputedOptions & AtomOptions;
export type CreateAtom = (
/**
 * Name of the atom that may be useful for debugging
 */
name: string, options?: AtomOptions) => Atom;
/**
 * Defines the signature for a function that creates a {@link ComputedAtom}.
 * @template T The type of the value held by the computed atom.
 */
export type CreateComputedAtom = <T>(
/**
 * Name of the atom that may be useful for debugging
 */
name: string, 
/**
 * A function used to calculate the atom value
 */
calculate: () => T, options?: ComputedAtomOptions) => ComputedAtom<T>;
/**
 * Options for configuring a {@link Reaction}.
 * This primarily allows specifying a custom scheduler for reaction execution.
 */
export type ReactionOptions = {
    /**
     * If scheduler is provided, the reaction will not run or rerun
     * immediately, it will be scheduled using the provided `scheduler`
     * function
     */
    scheduler?: (callback: () => void) => void;
};
/**
 * Represents an active reaction that tracks dependencies and performs side effects.
 * It provides a method to stop the reaction.
 */
export type Reaction = {
    /**
     * A function that may be called to stop the reaction, preventing it from
     * re-running and cleaning up its resources.
     */
    stop: () => void;
};
/**
 * Defines the signature for a function that creates a {@link Reaction}.
 * A reaction tracks dependencies and re-runs an effect function when they change.
 */
export type CreateReaction = (
/**
 * A function that will be called or scheduled immediately, and may
 * track atoms and computed atoms, and may perform side-effects. This
 * function will be automatically called or scheduled again when those
 * atoms and computed atoms change
 */
effect: () => void, options?: ReactionOptions) => Reaction;
/**
 * Represents the core API of a reactive system instance.
 * It provides methods for creating atoms, computed atoms, reactions,
 * and managing tracking and transactions.
 */
export type ReactiveInstance = {
    /**
     * Creates a reactive atom, i.e. a stripped down version of a reactive
     * signal. It does not concern itself with storing any data - it simply
     * can be reported to be observed and reported to be changed. The
     * association of data with the atom is the responsibility of the user
     */
    createAtom: CreateAtom;
    /**
     * Creates a computed reactive atom. Tracks accesses of other atoms and
     * computed atoms during the calculation and becomes dependent on them.
     * The calculation is cached and will only be recalculated when its
     * dependencies change. It only behaves reactively like this when there
     * is at least one reaction observing it - otherwise it behaves like a
     * getter: doesn't cache and always recalculates upon being read
     */
    createComputedAtom: CreateComputedAtom;
    /**
     * Creates a reaction that, similar to computed atoms, tracks accesses to
     * other atoms and computed atoms inside (unless those atoms are read inside
     * an `untrack` call). This reaction immediately runs or gets scheduled (if
     * `scheduler` is provided) and will rerun if its dependencies change. Reaction
     * is what ultimately activates reactivity of atoms and computed atoms. This
     * reactivity will be active until the reaction is stopped by calling
     * `reaction.stop()`
     */
    createReaction: CreateReaction;
    /**
     * Returns whether or not the reactive library is currently
     * tracking a derivation (e.g. during computed atom calculation
     * or the tracked part of a reaction)
     */
    isTracking: () => boolean;
    /**
     * Runs provided `action` but suspends derivation tracking while
     * the `action` runs
     */
    untrack: <T>(action: () => T) => T;
    /**
     * Runs provided `transaction` that may mutate multiple reactive atoms.
     * Reactions are not triggered until the end of the transaction. This
     * is a lower level API than `runAction`
     */
    runTransaction: <T>(transaction: () => T) => T;
    /**
     * Similar to `runTransaction` - runs provided `action` that may
     * mutate multiple reactive atoms, as one transaction. The difference
     * between `runTransaction` and `runAction` is that all reactive
     * atom mutations must run inside `runAction`, otherwise a
     * warning may be shown in console. So `runTransaction` must
     * generally also be called inside `runAction`. It is useful to
     * have a `runTransaction` as a separate function because we may
     * want to create functions that will internally call `runTransaction`
     * but will still require the user to call those functions inside
     * `runAction`
     */
    runAction: <T>(action: () => T) => T;
};
/**
 * Represents the core API of a reactive system that can be plugged into fluidstate.
 * `fluidstate` implements its own derivation tracking (for reactions and computed atoms)
 * and therefore does not require an `isTracking` method from the underlying layer.
 */
export type ReactiveLayer = Omit<ReactiveInstance, "isTracking">;
export type ReactiveRemoteOptions = {
    /**
     * A scheduler function that controls the timing of reactions from the
     * remote reactive system when they depend on data from the local system.
     *
     * When a reaction in the remote system observes data in the local system,
     * this scheduler (if provided) will be used to enqueue the execution
     * of that remote reaction. This allows the local system to dictate
     * when updates from the remote system are processed, crucial for environments
     * like game engines or UI frameworks that have specific update cycles (e.g.,
     * end of frame, next animation tick).
     *
     * The `callback` parameter is the function that, when executed, will run
     * the remote reaction's effect.
     *
     * If not provided, remote reactions may run according to their own system's
     * default scheduling or immediately upon dependency change.
     */
    scheduler?: (callback: () => void) => void;
};
/**
 * Represents a function to be executed as part of a reaction's cleanup process.
 * Cleanup functions are typically registered using `createCleanup` from within
 * a reaction's effect. They are called automatically when the reaction is stopped
 * or before it re-runs, allowing for resource management and teardown logic.
 */
export type ReactionCleanup = () => void;
