import AVFoundation
import Combine
import Foundation

public enum PlayerEngineType {
    case avPlayer
}

// Represents current owner of AVPlayerClient
public enum PlayerOwner: Equatable {
    case omniPlayer
    case snippetPlayer
    case none

    public var timeUpdateInterval: TimeInterval {
        switch self {
        case .snippetPlayer:
            return 0.1
        case .omniPlayer, .none:
            return 0.5
        }
    }
}

public protocol PlayerEngine: Sendable {
    // Setup and teardown - these need to remain async
    var setup: @Sendable () async throws -> Void { get }
    var teardown: @Sendable () -> Void { get }

    // Basic playback controls
    var play: @Sendable () -> Void { get }
    var pause: @Sendable () -> Void { get }
    var seek: @Sendable (CMTime) async throws -> Void { get }

    // Volume controls
    var setVolume: @Sendable (Float) -> Void { get }
    var getVolume: @Sendable () -> Float { get }

    // Content management - these need to remain async as they return values
    var replaceCurrentItem: @Sendable (String?) async throws -> CMTime { get }

    // Now playing info - this can be non-async since it's fire and forget
    var setupNowPlayingInfo: @Sendable (_ title: String, _ artist: String, _ artworkURL: String?, _ elapsedTime: CMTime, _ totalTime: CMTime) -> Void { get }

    // Observables - using AsyncStream instead of AnyPublisher
    var timeControlStatus: @Sendable () -> AsyncStream<AVPlayer.TimeControlStatus> { get }
    var periodicTime: @Sendable () -> AsyncStream<CMTime> { get }
    var didPlayToEndTime: @Sendable () -> AsyncStream<AVPlayerItem> { get }

    // State access - can be synchronous using cache
    var getCurrentItem: @Sendable () async -> AVPlayerItem? { get }
    var isPlaybackLikelyToKeepUp: @Sendable () async -> Bool { get }
    var getUnderlyingPlayer: @Sendable () -> Any { get }

    // Asset management - can be fire and forget
    var preloadAssets: @Sendable (_ urls: [URL]) async -> Void { get }
    var cancelPreload: @Sendable () async -> Void { get }

    // Time update configuration
    var setTimeUpdateInterval: @Sendable (TimeInterval) -> Void { get }

    // Owner tracking
    var setOwner: @Sendable (PlayerOwner) async -> Void { get }
    var getOwner: @Sendable () async -> PlayerOwner { get }
}
