import { EventObject, StateNode, TransitionDefinition, Snapshot, MachineContext, ActorLogic, MachineSnapshot } from "../index.js";
export type AnyStateNode = StateNode<any, any>;
type JSONSerializable<T extends object, U> = T & {
    toJSON: () => U;
};
type DirectedGraphLabel = JSONSerializable<{
    text: string;
}, {
    text: string;
}>;
export type DirectedGraphEdge = JSONSerializable<{
    id: string;
    source: AnyStateNode;
    target: AnyStateNode;
    label: DirectedGraphLabel;
    transition: TransitionDefinition<any, any>;
}, {
    source: string;
    target: string;
    label: ReturnType<DirectedGraphLabel['toJSON']>;
}>;
export type DirectedGraphNode = JSONSerializable<{
    id: string;
    stateNode: StateNode;
    children: DirectedGraphNode[];
    /** The edges representing all transitions from this `stateNode`. */
    edges: DirectedGraphEdge[];
}, {
    id: string;
    children: DirectedGraphNode[];
}>;
interface StatePlan<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> {
    /** The target state. */
    state: TSnapshot;
    /** The paths that reach the target state. */
    paths: Array<StatePath<TSnapshot, TEvent>>;
}
export interface StatePath<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> {
    /** The ending state of the path. */
    state: TSnapshot;
    /**
     * The ordered array of state-event pairs (steps) which reach the ending
     * `state`.
     */
    steps: Steps<TSnapshot, TEvent>;
    /** The combined weight of all steps in the path. */
    weight: number;
}
export interface StatePlanMap<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> {
    [key: string]: StatePlan<TSnapshot, TEvent>;
}
export interface Step<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> {
    /** The event that resulted in the current state */
    event: TEvent;
    /** The current state after taking the event. */
    state: TSnapshot;
}
export type Steps<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> = Array<Step<TSnapshot, TEvent>>;
type ExtractEvent<TEvent extends EventObject, TType extends TEvent['type']> = TEvent extends {
    type: TType;
} ? TEvent : never;
export interface VisitedContext<TState, TEvent> {
    vertices: Set<SerializedSnapshot>;
    edges: Set<SerializedEvent>;
    a?: TState | TEvent;
}
export interface SerializationConfig<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> {
    serializeState: (state: TSnapshot, event: TEvent | undefined, prevState?: TSnapshot) => string;
    serializeEvent: (event: TEvent) => string;
}
type SerializationOptions<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> = Partial<Pick<SerializationConfig<TSnapshot, TEvent>, 'serializeState' | 'serializeEvent'>>;
export type TraversalOptions<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject, TInput> = {
    input?: TInput;
} & SerializationOptions<TSnapshot, TEvent> & Partial<Pick<TraversalConfig<TSnapshot, TEvent>, 'events' | 'limit' | 'fromState' | 'stopWhen' | 'toState'>>;
export interface TraversalConfig<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> extends SerializationConfig<TSnapshot, TEvent> {
    events: readonly TEvent[] | ((state: TSnapshot) => readonly TEvent[]);
    /**
     * The maximum number of traversals to perform when calculating the state
     * transition adjacency map.
     *
     * @default `Infinity`
     */
    limit: number;
    fromState: TSnapshot | undefined;
    /** When true, traversal of the adjacency map will stop for that current state. */
    stopWhen: ((state: TSnapshot) => boolean) | undefined;
    toState: ((state: TSnapshot) => boolean) | undefined;
}
type Brand<T, Tag extends string> = T & {
    __tag: Tag;
};
export type SerializedSnapshot = Brand<string, 'state'>;
export type SerializedEvent = Brand<string, 'event'>;
export interface TestMeta<T, TContext extends MachineContext> {
    test?: (testContext: T, state: MachineSnapshot<TContext, any, any, any, any, any, any, // TMeta
    any>) => Promise<void> | void;
    description?: string | ((state: MachineSnapshot<TContext, any, any, any, any, any, any, // TMeta
    any>) => string);
    skip?: boolean;
}
interface TestStateResult {
    error: null | Error;
}
export interface TestStepResult {
    step: Step<any, any>;
    state: TestStateResult;
    event: {
        error: null | Error;
    };
}
export interface TestParam<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> {
    states?: {
        [key: string]: (state: TSnapshot) => void | Promise<void>;
    };
    events?: {
        [TEventType in TEvent['type']]?: EventExecutor<TSnapshot, {
            type: ExtractEvent<TEvent, TEventType>['type'];
        }>;
    };
}
export interface TestPath<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> extends StatePath<TSnapshot, TEvent> {
    description: string;
    /**
     * Tests and executes each step in `steps` sequentially, and then tests the
     * postcondition that the `state` is reached.
     */
    test: (params: TestParam<TSnapshot, TEvent>) => Promise<TestPathResult>;
}
export interface TestPathResult {
    steps: TestStepResult[];
    state: TestStateResult;
}
/**
 * Executes an effect using the `testContext` and `event` that triggers the
 * represented `event`.
 */
export type EventExecutor<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject> = (step: Step<TSnapshot, TEvent>) => Promise<any> | void;
export interface TestModelOptions<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject, TInput> extends TraversalOptions<TSnapshot, TEvent, TInput> {
    stateMatcher: (state: TSnapshot, stateKey: string) => boolean;
    logger: {
        log: (msg: string) => void;
        error: (msg: string) => void;
    };
    serializeTransition: (state: TSnapshot, event: TEvent | undefined, prevState?: TSnapshot) => string;
}
export type PathGenerator<TSnapshot extends Snapshot<unknown>, TEvent extends EventObject, TInput> = (behavior: ActorLogic<TSnapshot, TEvent, TInput>, options: TraversalOptions<TSnapshot, TEvent, TInput>) => Array<StatePath<TSnapshot, TEvent>>;
export interface AdjacencyValue<TState, TEvent> {
    state: TState;
    transitions: {
        [key: SerializedEvent]: {
            event: TEvent;
            state: TState;
        };
    };
}
export interface AdjacencyMap<TState, TEvent> {
    [key: SerializedSnapshot]: AdjacencyValue<TState, TEvent>;
}
export {};
