/**
 * aviation_state_machine.h — Playback state machine (one-function-per-state).
 *
 * Pure C implementation of the BBC SMP one-class-per-state pattern.
 * Instead of virtual classes, we use a dispatch table: each state has
 * handler functions for play/pause/seek/stop/onDecoderEvent. The
 * coordinator calls through the dispatch table.
 *
 * State transitions return the new state (or the same state for no-op).
 * Side effects (command events, domain events) are emitted via the
 * event bus passed through the context.
 *
 * Thread safety: The state machine itself is NOT thread-safe.
 * The coordinator must hold a mutex before calling any state function.
 */

#ifndef AVIATION_STATE_MACHINE_H
#define AVIATION_STATE_MACHINE_H

#include "aviation_event_bus.h"
#include "aviation_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/* ─── State context ───────────────────────────────────────────────── */

typedef void (*AviationCommandEmitter)(void *user_data, const AviationCommandEvent *event);
typedef void (*AviationDomainEmitter)(void *user_data, const AviationDomainEvent *event);

/**
 * Shared context passed to every state handler.
 * Provides access to current item, position, properties, and event bus.
 */
typedef struct {
    /* Current item */
    AviationMediaItem current_item;
    bool has_current_item;

    /* Current position */
    AviationMediaPosition position;

    /* Item source tracking */
    int32_t item_source; /* AviationItemSource */
    int32_t queue_index;

    /* Playback properties */
    double rate;
    double volume;
    bool muted;
    bool loop;

    /* Event bus for emitting events */
    AviationEventBus *event_bus;

    /* Optional deferred emitters owned by the coordinator. */
    AviationCommandEmitter command_emitter;
    AviationDomainEmitter domain_emitter;
    void *emitter_user_data;
} AviationPlaybackContext;

/* ─── State transition result ─────────────────────────────────────── */

/**
 * Result of a state handler call.
 * new_state: the state to transition to (may be same as current for no-op).
 * transitioned: true if a transition should occur.
 */
typedef struct {
    AviationPlaybackState new_state;
    bool transitioned;
} AviationStateResult;

/** Helper: no transition (stay in current state). */
static inline AviationStateResult aviation_state_noop(void) {
    AviationStateResult r = {AVIATION_STATE_IDLE, false};
    return r;
}

/** Helper: transition to a new state. */
static inline AviationStateResult aviation_state_transition(AviationPlaybackState new_state) {
    AviationStateResult r = {new_state, true};
    return r;
}

/* ─── State handler functions ─────────────────────────────────────── */

/**
 * State machine dispatch: handle a play command in the given state.
 * Emits command events on the context's event bus as side effects.
 */
AviationStateResult aviation_state_play(AviationPlaybackState state, AviationPlaybackContext *ctx);

/**
 * State machine dispatch: handle a pause command.
 */
AviationStateResult aviation_state_pause(AviationPlaybackState state, AviationPlaybackContext *ctx);

/**
 * State machine dispatch: handle a seek command.
 */
AviationStateResult aviation_state_seek(AviationPlaybackState state, int64_t position_ms, AviationPlaybackContext *ctx);

/**
 * State machine dispatch: handle a stop command.
 */
AviationStateResult aviation_state_stop(AviationPlaybackState state, AviationPlaybackContext *ctx);

/**
 * State machine dispatch: handle a decoder event.
 */
AviationStateResult aviation_state_on_decoder_event(AviationPlaybackState state, const AviationDecoderEvent *event,
                                                    AviationPlaybackContext *ctx);

/* ─── Context helpers ─────────────────────────────────────────────── */

/** Initialize a playback context with defaults. */
void aviation_context_init(AviationPlaybackContext *ctx, AviationEventBus *bus);

/** Emit a command event on the context's event bus. */
void aviation_context_emit_command(AviationPlaybackContext *ctx, const AviationCommandEvent *event);

/** Emit a domain event on the context's event bus. */
void aviation_context_emit_domain(AviationPlaybackContext *ctx, const AviationDomainEvent *event);

#ifdef __cplusplus
}
#endif

#endif /* AVIATION_STATE_MACHINE_H */
