import { InjectStoreConfig } from '@zedux/atoms';
import { MachineStore } from './MachineStore.js';
import { MachineHook, MachineStateShape } from './types.js';
declare type ArrToUnion<S extends string[]> = S extends [infer K, ...infer Rest] ? Rest extends string[] ? K | ArrToUnion<Rest> : never : never;
export declare type InjectMachineStoreParams<States extends MachineState[], Context extends Record<string, any> | undefined = undefined> = [
    statesFactory: (state: <Name extends string>(stateName: Name) => MachineState<Context, Name>) => [...States],
    initialContext?: Context,
    config?: {
        guard?: (currentState: MachineStateShape<MapStatesToStateNames<States>, Context>, nextValue: MapStatesToStateNames<States>) => boolean;
        onTransition?: MachineHook<MapStatesToStateNames<States>, MapStatesToEvents<States, Context>, Context>;
    } & InjectStoreConfig
];
export interface MachineState<Context extends Record<string, any> | undefined = any, Name extends string = string, Events extends string[] = [], ChildStates extends string[] = [Name]> {
    on: <E extends string, S extends string>(eventName: E, nextState: S, guard?: (context: Context) => boolean) => MachineState<Context, Name, [...Events, E], [...ChildStates, S]>;
    onEnter: (listener: MachineHook<ArrToUnion<ChildStates>, ArrToUnion<Events>, Context>) => MachineState<Context, Name, Events, ChildStates>;
    onLeave: (listener: MachineHook<ArrToUnion<ChildStates>, ArrToUnion<Events>, Context>) => MachineState<Context, Name, Events, ChildStates>;
    stateName: Name;
}
declare type MapStatesToStateNames<States extends MachineState[], Context extends Record<string, any> | undefined = undefined> = States extends [infer K, ...infer Rest] ? K extends MachineState ? Rest extends MachineState[] ? StateNameType<K> | ArrToUnion<StateChildStatesType<K>> | MapStatesToStateNames<Rest, Context> : never : never : never;
declare type MapStatesToEvents<States extends MachineState[], Context extends Record<string, any> | undefined = undefined> = States extends [infer K, ...infer Rest] ? K extends MachineState ? Rest extends MachineState[] ? ArrToUnion<StateEventsType<K>> | MapStatesToEvents<Rest, Context> : ArrToUnion<StateEventsType<K>> : never : never;
declare type StateChildStatesType<S extends MachineState> = S extends MachineState<any, string, string[], infer ChildStates> ? ChildStates : never;
declare type StateEventsType<S extends MachineState> = S extends MachineState<any, string, infer Events> ? Events : never;
declare type StateNameType<S extends MachineState> = S extends MachineState<any, infer Name> ? Name : never;
/**
 * Create a MachineStore. Pass a statesFactory
 *
 * The first state in the state list returned from your statesFactory will
 * become the initial state (`.value`) of the store.
 *
 * Registers an effect that listens to all store changes and calls the
 * configured listeners appropriately.
 *
 * ```ts
 * const store = injectMachineStore(state => [
 *   state('a')
 *     .on('next', 'b', localGuard)
 *     .onEnter(enterListener)
 *     .onLeave(leaveListener),
 *   state('b').on('next', 'a')
 * ], initialContext, { guard, onTransition })
 * ```
 *
 * Set a universal transition guard via the 3rd `config` object param. This
 * guard will be called every time a valid transition is about to occur. It will
 * be called with the current `.context` value and should return a boolean.
 * Return true to allow the transition, or any falsy value to deny it.
 *
 * Set a universal `onTransition` listener via the 3rd `config` object param.
 * This listener will be called every time the machine transitions to a new
 * state (after the state is updated). It will be called with 2 params: The
 * current MachineStore and the storeEffect of the action that transitioned the
 * store. For example, use `storeEffect.oldState.value` to see what state the
 * machine just transitioned from.
 *
 * @param statesFactory Required. A function. Use the received state factory to
 * create a list of states for the machine and specify their transitions,
 * guards, and listeners.
 * @param initialContext Optional. An object or undefined. Will be set as the
 * initial `.context` value of the machine store's state.
 * @param config Optional. An object with 2 additional properties: `guard` and
 * `onTransition`.
 */
export declare const injectMachineStore: <States extends MachineState[], Context extends Record<string, any> | undefined = undefined>(...[statesFactory, initialContext, config]: InjectMachineStoreParams<States, Context>) => MachineStore<MapStatesToStateNames<States, Context>, MapStatesToEvents<States, Context>, Context>;
export {};
