/**
 * aviation_event_bus.h — Thread-safe event pub/sub for the domain core.
 *
 * Two event channels:
 *
 * 1. Command events (domain -> adapters):
 *    Emitted by the state machine when it needs an adapter to perform
 *    an action (load, play, pause, seek, etc.).
 *
 * 2. Domain events (domain -> observers):
 *    Emitted by the coordinator for observation purposes (state changes,
 *    position updates, item changes, errors).
 *
 * Thread safety:
 * - Listeners are registered under a mutex.
 * - Events are emitted using snapshot-then-fire: snapshot listeners under
 *   the mutex, then invoke them outside the mutex to prevent deadlocks
 *   if a listener re-enters the event bus.
 *
 * Listener IDs:
 * - Each subscription returns a uint32_t ID for later unsubscription.
 *
 * Pure C. No platform imports.
 */

#ifndef AVIATION_EVENT_BUS_H
#define AVIATION_EVENT_BUS_H

#include "aviation_types.h"

#ifdef __cplusplus
extern "C" {
#endif

/** Opaque handle to an event bus instance. */
typedef struct AviationEventBus AviationEventBus;

/* ─── Lifecycle ───────────────────────────────────────────────────── */

/** Create a new event bus. Caller must destroy with aviation_event_bus_destroy(). */
AviationEventBus *aviation_event_bus_create(void);

/** Destroy an event bus and free all resources. */
void aviation_event_bus_destroy(AviationEventBus *bus);

/* ─── Command event channel ───────────────────────────────────────── */

/**
 * Subscribe to command events.
 * Returns a subscription ID for later unsubscription, or 0 when the bus is
 * NULL, the listener is NULL, or the channel already has
 * AVIATION_MAX_LISTENERS listeners. 0 is never a valid subscription ID —
 * callers must treat it as an explicit failure, not ignore it.
 */
uint32_t aviation_event_bus_subscribe_commands(AviationEventBus *bus, AviationCommandListener listener,
                                               void *user_data);

/** Unsubscribe from command events by subscription ID. Returns the user_data pointer for cleanup. */
void *aviation_event_bus_unsubscribe_commands(AviationEventBus *bus, uint32_t subscription_id);

/** Emit a command event to all subscribers (snapshot-then-fire). */
void aviation_event_bus_emit_command(AviationEventBus *bus, const AviationCommandEvent *event);

/* ─── Domain event channel ────────────────────────────────────────── */

/**
 * Subscribe to domain events.
 * Returns a subscription ID for later unsubscription, or 0 on failure
 * (NULL arguments or channel at AVIATION_MAX_LISTENERS) — same contract
 * as aviation_event_bus_subscribe_commands().
 */
uint32_t aviation_event_bus_subscribe_domain(AviationEventBus *bus, AviationDomainListener listener, void *user_data);

/** Unsubscribe from domain events by subscription ID. Returns the user_data pointer for cleanup. */
void *aviation_event_bus_unsubscribe_domain(AviationEventBus *bus, uint32_t subscription_id);

/** Emit a domain event to all subscribers (snapshot-then-fire). */
void aviation_event_bus_emit_domain(AviationEventBus *bus, const AviationDomainEvent *event);

/* ─── Teardown ────────────────────────────────────────────────────── */

/** Remove all listeners from both channels. */
void aviation_event_bus_remove_all_listeners(AviationEventBus *bus);

#ifdef __cplusplus
}
#endif

#endif /* AVIATION_EVENT_BUS_H */
