import { DependencyLifecycle } from '../../types';
/**
 * Configuration for a KOS state machine.
 *
 * @template TState Union type of valid state strings
 * @template TEvent Union type of valid event strings
 *
 * @example
 * ```typescript
 * const config: KosStateMachineConfig<'idle' | 'active', 'START' | 'STOP'> = {
 *   initial: 'idle',
 *   initializeAt: DependencyLifecycle.READY,
 *   states: {
 *     idle: { on: { START: 'active' } },
 *     active: { on: { STOP: 'idle' } }
 *   }
 * };
 * ```
 *
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export interface KosStateMachineConfig<TState extends string, TEvent extends string> {
    /**
     * The initial state when the state machine is initialized.
     * This state will be set when the FSM reaches its configured lifecycle phase.
     */
    initial: TState;
    /**
     * The lifecycle phase at which the state machine should be initialized.
     * Before this phase, currentState will be undefined and isFsmInitialized will be false.
     *
     * @default DependencyLifecycle.READY
     *
     * @example
     * ```typescript
     * // FSM initializes when model is ready (most common)
     * initializeAt: DependencyLifecycle.READY
     *
     * // FSM initializes only when UI activates the model
     * initializeAt: DependencyLifecycle.ACTIVATE
     *
     * // FSM initializes during model initialization (rare)
     * initializeAt: DependencyLifecycle.INIT
     * ```
     */
    initializeAt?: DependencyLifecycle;
    /**
     * State machine definition mapping states to their allowed transitions.
     *
     * @example
     * ```typescript
     * states: {
     *   idle: { on: { PREPARE: 'preparing' } },
     *   preparing: { on: { READY: 'ready', ERROR: 'error' } },
     *   ready: { on: { POUR: 'pouring' } },
     *   pouring: { on: { COMPLETE: 'idle', ERROR: 'error' } },
     *   error: { on: { RESET: 'idle' } }
     * }
     * ```
     */
    states: Record<TState, {
        /**
         * Mapping of events to target states.
         * When an event occurs in this state, transition to the target state.
         */
        on?: Partial<Record<TEvent, TState>>;
        /**
         * Event to auto-send when an async @kosStateEntry handler resolves.
         * Only triggers if the FSM is still in this state when the handler completes.
         *
         * @example
         * ```typescript
         * cancelling: {
         *   on: { CANCELLED: 'cancelled', FAIL: 'error' },
         *   onDone: 'CANCELLED',  // auto-transition on success
         *   onError: 'FAIL',      // auto-transition on failure
         * }
         * ```
         */
        onDone?: TEvent;
        /**
         * Event to auto-send when an async @kosStateEntry handler rejects.
         * Only triggers if the FSM is still in this state when the handler fails.
         */
        onError?: TEvent;
    }>;
}
/**
 * Options for configuring state machine behavior.
 *
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export interface KosStateMachineOptions {
    /**
     * Property name for storing the current state.
     *
     * @default "currentState"
     */
    stateProperty?: string;
    /**
     * Whether to track state history.
     * When enabled, a stateHistory array is maintained with timestamps and events.
     *
     * @default false
     */
    trackHistory?: boolean;
    /**
     * Whether to throw errors on invalid transitions.
     * When false, invalid transitions are logged as warnings instead.
     *
     * @default true
     */
    throwOnInvalid?: boolean;
    /**
     * Optional function to compute the initial FSM state dynamically at instance creation time.
     * When provided, this function is called with the model instance and its return value
     * is used as the initial state instead of the static `initial` from the config.
     *
     * This is useful for ViewModels that wrap an existing model which may already be in
     * a non-default state (e.g., a connection that is already CONNECTED on app load).
     *
     * Note: Entry handlers are NOT called for the computed initial state since it
     * represents current state, not a transition.
     *
     * @param instance The model/ViewModel instance (after constructor, before makeAutoObservable)
     * @returns The initial FSM state to use
     *
     * @example
     * ```typescript
     * @kosStateMachine(fsmConfig, {
     *   computeInitialState: (instance) => {
     *     const state = instance.connection?.state;
     *     return state === 'CONNECTED' ? 'connected' : 'inactive';
     *   }
     * })
     * ```
     * @kosApiLevel 21
     */
    computeInitialState?: (instance: any) => string;
}
/**
 * Interface for models using the @kosStateMachine decorator.
 *
 * **IMPORTANT**: Use TypeScript interface merging to add FSM properties to your model class.
 * This provides full type safety and IntelliSense support for all injected FSM functionality.
 *
 * ## Interface Merging Pattern
 *
 * ```typescript
 * // 1. Define state and event types
 * type PourState = 'idle' | 'preparing' | 'ready' | 'pouring' | 'error';
 * type PourEvent = 'PREPARE' | 'READY' | 'POUR' | 'COMPLETE' | 'ERROR';
 *
 * // 2. Declare interface merging BEFORE the class
 * interface DispenserModelImpl extends KosStateMachineAware<PourState, PourEvent> {}
 *
 * // 3. Apply decorators and implement the class
 * @kosModel({ modelTypeId: "dispenser-model" })
 * @kosStateMachine<PourState, PourEvent>({
 *   initial: 'idle',
 *   initializeAt: DependencyLifecycle.READY,
 *   states: {
 *     idle: { on: { PREPARE: 'preparing' } },
 *     preparing: { on: { READY: 'ready', ERROR: 'error' } },
 *     ready: { on: { POUR: 'pouring' } },
 *     pouring: { on: { COMPLETE: 'idle', ERROR: 'error' } },
 *     error: {}
 *   }
 * })
 * export class DispenserModelImpl implements IKosDataModel {
 *   // All FSM properties are now available with full type safety
 * }
 * ```
 *
 * ## Lifecycle-Aware Initialization
 *
 * The FSM is uninitialized until the configured lifecycle phase:
 * - Before initialization: `currentState === undefined`, `isFsmInitialized === false`
 * - After initialization: `currentState === initial`, `isFsmInitialized === true`
 *
 * ```typescript
 * @kosStateMachine({
 *   initial: 'idle',
 *   initializeAt: DependencyLifecycle.READY, // FSM starts when model is ready
 *   states: { ... }
 * })
 * class MyModel {
 *   async ready(): Promise<void> {
 *     // Before this completes: this.currentState === undefined
 *     // After this completes: this.currentState === 'idle'
 *   }
 * }
 * ```
 *
 * ## Injected Properties and Methods
 *
 * The decorator automatically injects the following members:
 *
 * - **`currentState`**: Current state (undefined until FSM initialized, observable)
 * - **`isFsmInitialized`**: Boolean indicating if FSM has been initialized
 * - **`isTransitioning`**: Boolean indicating if a transition is in progress
 * - **`allowedTransitions`**: Computed array of valid events for current state
 * - **`transition(event)`**: Method to trigger state transitions
 * - **`canTransition(event)`**: Check if a transition is valid from current state
 * - **`isInState(state)`**: Check if currently in a specific state
 * - **`stateHistory`**: Array of historical states (if trackHistory enabled)
 *
 * All properties are reactive and will automatically update UI components when state changes.
 *
 * @template TState Union type of valid state strings
 * @template TEvent Union type of valid event strings
 *
 * @see {@link kosStateMachine} - The decorator function
 * @see {@link KosStateMachineConfig} - Configuration interface
 * @see {@link KosStateMachineOptions} - Options interface
 *
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export interface KosStateMachineAware<TState extends string, TEvent extends string> {
    /**
     * Current state of the state machine.
     * Observable property that updates automatically via @kosModel.
     * Always initialized to the initial state immediately.
     */
    currentState: TState;
    /**
     * Indicates whether the state machine has been initialized.
     * FSM initializes at the configured lifecycle phase (READY, ACTIVATE, etc.).
     *
     * - Before initialization: `false`, `currentState === undefined`
     * - After initialization: `true`, `currentState === initial`
     */
    readonly isFsmInitialized: boolean;
    /**
     * Indicates whether a state transition is currently in progress.
     * Observable property that updates during transitions.
     */
    isTransitioning: boolean;
    /**
     * Computed array of valid events that can be triggered from the current state.
     * Updates automatically when state changes.
     * Returns empty array if FSM is not initialized.
     */
    readonly allowedTransitions: TEvent[];
    /**
     * Trigger a state transition by event.
     *
     * @param event The event to trigger
     * @throws Error if FSM not initialized (unless `throwOnInvalid` is false)
     * @throws Error if transition is invalid (unless `throwOnInvalid` is false)
     *
     * @example
     * ```typescript
     * this.transition('START'); // idle -> active
     * this.transition('STOP');  // active -> idle
     * ```
     */
    transition(event: TEvent): void;
    /**
     * Check if a transition is valid from the current state.
     * Returns false if FSM is not initialized.
     *
     * @param event The event to check
     * @returns true if the transition is valid, false otherwise
     *
     * @example
     * ```typescript
     * if (this.canTransition('START')) {
     *   this.transition('START');
     * }
     * ```
     */
    canTransition(event: TEvent): boolean;
    /**
     * Check if the state machine is currently in a specific state.
     * Returns false if FSM is not initialized.
     *
     * @param state The state to check
     * @returns true if currently in the specified state, false otherwise
     *
     * @example
     * ```typescript
     * if (this.isInState('idle')) {
     *   console.log('System is idle');
     * }
     * ```
     */
    isInState(state: TState): boolean;
    /**
     * History of state transitions (if trackHistory is enabled).
     * Each entry contains the state, timestamp, and optional event that caused the transition.
     *
     * Only available when `trackHistory: true` is set in options.
     */
    stateHistory?: Array<{
        state: TState;
        timestamp: Date;
        event?: TEvent;
    }>;
}
/**
 * Class decorator that adds finite state machine capabilities to a KOS model.
 *
 * This decorator eliminates manual state management boilerplate by:
 * - **Adding lifecycle-aware FSM initialization** at configured phase (READY, ACTIVATE, etc.)
 * - **Managing state transitions** automatically with validation
 * - **Providing observable state** that integrates with @kosModel reactive system
 * - **Supporting entry/exit handlers** via @kosStateEntry and @kosStateExit decorators
 * - **Enabling state guards** via @kosStateGuard decorator
 *
 * ## Two-Level State System
 *
 * **Framework Lifecycle (Universal, Not Customizable):**
 * - CREATED → INIT → LOAD → READY → ACTIVATE → UNLOAD → DESTROY
 * - Managed by KOS framework
 * - Same for all models
 *
 * **Application FSM (This Decorator):**
 * - Runs WITHIN an active model
 * - Application-specific business logic
 * - Different for each model type
 * - Examples: Pour states, connection states, workflow states
 *
 * ## Lifecycle Integration
 *
 * The FSM initializes at the configured lifecycle phase:
 *
 * ```typescript
 * @kosStateMachine({
 *   initial: 'idle',
 *   initializeAt: DependencyLifecycle.READY, // Default
 *   states: { ... }
 * })
 * ```
 *
 * - **INIT**: FSM needs to be active during model initialization (rare)
 * - **READY**: FSM operational as soon as data loaded (most common)
 * - **ACTIVATE**: FSM only relevant when UI is active (UI-bound models)
 *
 * ## TypeScript Usage
 *
 * **IMPORTANT**: Use TypeScript interface merging to get proper type information:
 *
 * ```typescript
 * type MyState = 'idle' | 'active';
 * type MyEvent = 'START' | 'STOP';
 *
 * interface MyModelImpl extends KosStateMachineAware<MyState, MyEvent> {}
 *
 * @kosStateMachine<MyState, MyEvent>({ ... })
 * class MyModelImpl implements IKosDataModel {
 *   // All FSM properties are now available with full type safety
 * }
 * ```
 *
 * @param config State machine configuration
 * @param options Optional configuration for FSM behavior
 * @returns A class decorator that modifies the target class prototype
 *
 * @see {@link KosStateMachineAware} - Interface for TypeScript merging
 * @see {@link KosStateMachineConfig} - Configuration interface
 * @see {@link KosStateMachineOptions} - Options interface
 *
 * @example
 * ```typescript
 * // Basic FSM with default READY initialization
 * type PourState = 'idle' | 'pouring' | 'complete';
 * type PourEvent = 'START' | 'FINISH';
 *
 * interface PourModelImpl extends KosStateMachineAware<PourState, PourEvent> {}
 *
 * @kosModel({ modelTypeId: "pour-model" })
 * @kosStateMachine<PourState, PourEvent>({
 *   initial: 'idle',
 *   states: {
 *     idle: { on: { START: 'pouring' } },
 *     pouring: { on: { FINISH: 'complete' } },
 *     complete: {}
 *   }
 * })
 * class PourModelImpl implements IKosDataModel {
 *   async ready(): Promise<void> {
 *     // After this completes, FSM is initialized to 'idle'
 *   }
 *
 *   startPour(): void {
 *     this.transition('START'); // idle -> pouring
 *   }
 * }
 * ```
 *
 * @example
 * ```typescript
 * // UI-bound FSM with ACTIVATE initialization
 * type WorkflowState = 'draft' | 'review' | 'approved';
 * type WorkflowEvent = 'SUBMIT' | 'APPROVE' | 'REJECT';
 *
 * interface DocumentModelImpl extends KosStateMachineAware<WorkflowState, WorkflowEvent> {}
 *
 * @kosModel({ modelTypeId: "document-model" })
 * @kosStateMachine<WorkflowState, WorkflowEvent>({
 *   initial: 'draft',
 *   initializeAt: DependencyLifecycle.ACTIVATE, // UI-bound
 *   states: {
 *     draft: { on: { SUBMIT: 'review' } },
 *     review: { on: { APPROVE: 'approved', REJECT: 'draft' } },
 *     approved: {}
 *   }
 * })
 * class DocumentModelImpl implements IKosDataModel {
 *   // FSM only initializes when UI activates this model
 * }
 * ```
 *
 * @example
 * ```typescript
 * // FSM with history tracking
 * interface HistoryModelImpl extends KosStateMachineAware<'idle' | 'active', 'TOGGLE'> {}
 *
 * @kosStateMachine<'idle' | 'active', 'TOGGLE'>(
 *   {
 *     initial: 'idle',
 *     states: {
 *       idle: { on: { TOGGLE: 'active' } },
 *       active: { on: { TOGGLE: 'idle' } }
 *     }
 *   },
 *   {
 *     trackHistory: true,
 *     stateProperty: 'status'
 *   }
 * )
 * class HistoryModelImpl implements IKosDataModel {
 *   // Access via this.stateHistory
 * }
 * ```
 *
 * @category KOS Model Decorator
 * @since 2.1.0
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export declare function kosStateMachine<TState extends string, TEvent extends string>(config: KosStateMachineConfig<TState, TEvent>, options?: KosStateMachineOptions): ClassDecorator;
/**
 * Method decorator that marks a method as a state entry handler.
 * The decorated method will be called when the state machine enters the specified state.
 *
 * @param state The state to handle entry for
 * @returns A method decorator
 *
 * @example
 * ```typescript
 * @kosStateEntry('pouring')
 * handlePouringStart(): void {
 *   this.logger.info('Pour started');
 *   EventBus.publish(TOPIC_POUR_STARTED, { id: this.id });
 * }
 * ```
 *
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export declare function kosStateEntry<TState extends string>(state: TState): MethodDecorator;
/**
 * Method decorator that marks a method as a state exit handler.
 * The decorated method will be called when the state machine exits the specified state.
 *
 * @param state The state to handle exit for
 * @returns A method decorator
 *
 * @example
 * ```typescript
 * @kosStateExit('pouring')
 * handlePouringEnd(): void {
 *   this.logger.info('Pour ended');
 *   EventBus.publish(TOPIC_POUR_ENDED, { id: this.id });
 * }
 * ```
 *
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export declare function kosStateExit<TState extends string>(state: TState): MethodDecorator;
/**
 * Options for @kosStateGuard decorator.
 *
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export interface KosStateGuardOptions<TState extends string> {
    /**
     * Array of states in which the decorated method can be called.
     * The method will throw an error (or log a warning) if called from any other state.
     */
    allowedStates: TState[];
    /**
     * Whether to throw an error on invalid state.
     * When false, logs a warning instead.
     *
     * @default true (uses the FSM's throwOnInvalid setting)
     */
    throwOnInvalid?: boolean;
}
/**
 * Method decorator that guards a method with state validation.
 * The decorated method can only be called when the state machine is in one of the allowed states.
 *
 * **IMPORTANT**: This decorator gracefully handles uninitialized FSM:
 * - If FSM is not yet initialized, the guard allows the method to proceed
 * - Once FSM is initialized, the guard enforces state validation
 *
 * @param options Guard configuration
 * @returns A method decorator
 *
 * @example
 * ```typescript
 * @kosStateGuard({ allowedStates: ['ready'] })
 * async pourBeverage(bevId: string): Promise<void> {
 *   // This method can only be called when currentState === 'ready'
 *   this.transition('POUR');
 *   await this.deviceService.dispense(bevId);
 *   this.transition('COMPLETE');
 * }
 * ```
 *
 * @kosService core.state-machine
 * @kosApiLevel 15
 */
export declare function kosStateGuard<TState extends string>(options: KosStateGuardOptions<TState>): MethodDecorator;
//# sourceMappingURL=kos-state-machine.d.ts.map