import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow

/**
 * A variant of [StateFlow] that allows an initial state
 */
interface NoInitialStateFlow<T> : Flow<T> {

    /**
     * Throws an exception if called when this [NoInitialStateFlow] has not been initialized with a state yet.
     * @see [StateFlow.value]
     */
    val value: T

    /**
     * Returns the [value], or `null` if this [NoInitialStateFlow] has not been initialized yet
     */
    val valueOrNull: T?

    /**
     * Returns the [value] immediately if this [NoInitialStateFlow] has been initialized, or suspends until
     * it is initialized
     */
    suspend fun value(): T
}

/**
 * A variant of [MutableStateFlow] that allows an initial state to be set after construction
 */
interface MutableNoInitialStateFlow<T> : NoInitialStateFlow<T> {

    /**
     * See [MutableStateFlow.value]
     */
    override var value: T
}

/**
 * Constructor for [MutableNoInitialStateFlow]
 */
@Suppress("FunctionName")
fun <T> MutableNoInitialStateFlow(): MutableNoInitialStateFlow<T> = NoInitialStateFlowInternalImpl()