package theorycrafter.utils

import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf


/**
 * A registry of counters of (re)compositions.
 *
 * The purpose is to allow validation of the number of recompositions in tests.
 */
class CompositionCounters {


    /**
     * A counter.
     */
    private class Counter(var value: Int = 0)


    /**
     * Maps tags to counters.
     */
    private val counterByTag = mutableMapOf<String, Counter>()


    /**
     * Increases the counter with the given tag by one.
     */
    fun recomposed(tag: String) {
        val counter = counterByTag.getOrPut(tag, ::Counter)
        counter.value += 1
    }


    /**
     * Returns the number of times the given tag has been recomposed.
     */
    operator fun get(tag: String): Int {
        return counterByTag[tag]?.value ?: 0
    }


    /**
     * Resets all composition counters to 0.
     */
    fun reset() {
        counterByTag.clear()
    }


    companion object {

        /**
         * If [LocalCompositionCounters] is not null, increases the counter with the given tag by one; otherwise does nothing.
         */
        @Suppress("NOTHING_TO_INLINE")
        @Composable
        inline fun recomposed(tag: String) {
            LocalCompositionCounters.current?.recomposed(tag)
        }


    }


}


/**
 * A composition local of a [CompositionCounters] instance.
 *
 * The instance will be non-null only when running tests.
 */
val LocalCompositionCounters = staticCompositionLocalOf<CompositionCounters?> { null }


/**
 * Provides the given [CompositionCounters] to the given content.
 */
@Composable
fun ProvideCompositionCounters(compositionCounters: CompositionCounters, content: @Composable () -> Unit) {
    CompositionLocalProvider(
        LocalCompositionCounters provides compositionCounters,
        content = content
    )
}