import Foundation

/// A service that captures audio from a microphone for the Recording feature.
///
/// ``RecordingView`` attaches the service to its model at initialization, so the audio capture can be swapped without touching the feature's
/// state machine — for example, with a real microphone backend in the app, or with a mock in unit tests.
public protocol Capturing: Sendable {

    // MARK: Properties

    /// The stream of events the service emits outside its method calls.
    ///
    /// Defaults to an empty stream that finishes immediately, for services that emit no events.
    var events: AsyncStream<CapturingEvent> { get }

    // MARK: Methods

    /// Starts a new audio recording from the microphone.
    func start() async throws

    /// Pauses the ongoing recording.
    func pause() async throws

    /// Resumes a paused recording.
    func resume() async throws

    /// Stops the recording.
    ///
    /// - Returns: The location of the audio file captured since the recording started.
    func stop() async throws -> URL

}

// MARK: - Implementations

public extension Capturing {

    /// The empty stream of events, which finishes immediately, for services that emit no events.
    var events: AsyncStream<CapturingEvent> {
        AsyncStream { continuation in
            continuation.finish()
        }
    }

}

// MARK: - Events

/// An event emitted by a ``Capturing`` service outside its method calls.
public enum CapturingEvent: Equatable, Sendable {
    /// The system interrupted the ongoing capture, pausing it.
    case interrupted
    /// The system ended the interruption of the capture, hinting whether the capture may resume right away.
    case interruptionEnded(shouldResume: Bool)
}
