package com.fabledsword.minstrel.player.output

import com.fabledsword.minstrel.player.output.upnp.AVTransportClient
import com.fabledsword.minstrel.player.output.upnp.RenderingControlClient
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject
import javax.inject.Singleton

/**
 * Shared singleton handle to the currently-active UPnP route's transport
 * + rendering clients. Decouples [com.fabledsword.minstrel.player.MinstrelForwardingPlayer]
 * from [OutputPickerController] -- the picker writes; the forwarding
 * player reads. Null = no UPnP active (local ExoPlayer path).
 */
data class ActiveUpnp(
    val routeId: String,
    val routeName: String,
    val avTransport: AVTransportClient,
    val rendering: RenderingControlClient?,
)

@Singleton
class ActiveUpnpHolder @Inject constructor() {

    private val internal = MutableStateFlow<ActiveUpnp?>(null)
    val active: StateFlow<ActiveUpnp?> = internal.asStateFlow()

    /**
     * Pending route id during selectUpnp's queue-load window. Set when
     * loadQueueOnSonos starts; cleared on completion (success or failure).
     * ForwardingPlayer overrides treat (target != null && active == null)
     * as "UPnP intended but SOAP not yet wired" -- drop transport commands
     * silently rather than send them to a half-loaded queue.
     */
    private val targetInternal = MutableStateFlow<String?>(null)
    val target: StateFlow<String?> = targetInternal.asStateFlow()

    fun set(active: ActiveUpnp?) { internal.value = active }

    fun setTarget(routeId: String?) { targetInternal.value = routeId }
}
