import { StatePropertyTypes } from '../../types';
/**
 * Configuration options for StateBean model instances.
 *
 * This interface defines the configuration options for the StateBean model,
 * specifying which state path the model should monitor for real-time updates.
 *
 * @example Basic StateBean Model Creation
 * ```typescript
 * // Monitor device operational status
 * const deviceState = StateBean.instance('device-status')
 *   .options({ path: 'device.operational.status' })
 *   .build();
 *
 * // Monitor system health metrics
 * const healthState = StateBean.instance('system-health')
 *   .options({ path: 'system.health.metrics' })
 *   .build();
 * ```
 *
 * @example Path Patterns
 * ```typescript
 * // Different path patterns for different use cases
 * const networkOptions: StateBeanOptions = {
 *   path: 'network.interfaces.primary' // Network interface state
 * };
 *
 * const pumpOptions: StateBeanOptions = {
 *   path: 'assembly.pumps.status' // Pump system state
 * };
 *
 * const brewingOptions: StateBeanOptions = {
 *   path: 'beverage.brewing.process' // Brewing process state
 * };
 * ```
 *
 * @example Hierarchical State Organization
 * ```typescript
 * // Use dot notation for hierarchical state paths
 * const parentState = StateBean.instance('parent')
 *   .options({ path: 'system' })
 *   .build();
 *
 * const childState = StateBean.instance('child')
 *   .options({ path: 'system.subsystem.component' })
 *   .build();
 * ```
 *
 * @kosService core.state-bean
 * @category Model Configuration
 * @category State Management
 */
export interface StateBeanOptions {
  /**
   * State path to monitor for updates using dot notation hierarchy.
   * This path corresponds to the WebSocket topic `/kos/state/{path}` for real-time updates.
   *
   * @example "device.operational.status"
   * @example "network.interfaces.primary"
   * @example "assembly.pumps.status"
   */
  path: string;
}

/**
 * Type-safe keys for state properties within a StateBean.
 *
 * @template T - The state property type mapping
 */
type StateKeys<T extends Record<string, StatePropertyTypes>> = keyof T;

/**
 * Reactive Map-based storage for state properties with type safety.
 *
 * This Map provides efficient storage and retrieval of state properties with automatic
 * reactivity through MobX observables. The Map structure allows for dynamic property
 * addition/removal while maintaining type safety for known properties.
 *
 * @example Accessing State Properties
 * ```typescript
 * // Define typed state interface
 * interface PumpState {
 *   active: boolean;
 *   flowRate: number;
 *   temperature: number;
 *   lastMaintenance: string;
 * }
 *
 * const pumpState = StateBean.instance('pump-monitor')
 *   .options({ path: 'assembly.pumps.pump1' })
 *   .build() as StateBean<PumpState>;
 *
 * // Type-safe property access
 * const isActive = pumpState.props.get('active') as boolean;
 * const currentFlow = pumpState.props.get('flowRate') as number;
 * const temp = pumpState.props.get('temperature') as number;
 * const maintenance = pumpState.props.get('lastMaintenance') as string;
 * ```
 *
 * @template T - The state property type mapping
 *
 * @kosService core.state-bean
 * @group KOS Model
 * @category Types
 */
export type StatePropsMap<T> = Map<StateKeys<T>, T[keyof T]>;

/**
 * State Bean Model interface - maintains the state of KOS device state properties.
 *
 * This interface represents the public API for StateBean models, providing reactive
 * access to device state properties through an observable Map structure. The interface
 * supports real-time synchronization with device state via WebSocket topics.
 *
 * @kosService core.state-bean
 * @group KOS Model
 * @category Model Interface
 */
export interface StateBeanModel<
  T extends Record<string, StatePropertyTypes> = Record<
    string,
    StatePropertyTypes
  >
> {
  /** Unique model identifier */
  id: string;
  /** State path being monitored */
  path: string;
  /** Reactive Map of state properties */
  props: StatePropsMap<T>;
  /** Update model configuration */
  updateModel(options: StateBeanOptions): void;
}
