package com.pixelized.desktop.lwa.ui.overlay.roll

import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.coroutines.resume


/**
 * Build on the SnackbarHostState model.
 * @see [androidx.compose.material.SnackbarHostState]
 */
@Stable
class RollHostState {

    private val mutex = Mutex()

    private val currentRollAction = mutableStateOf<RollAction?>(null)
    val rollAction: State<RollAction?> get() = currentRollAction

    suspend fun showRollOverlay(
        roll: RollAction.Uio,
    ): RollResult = mutex.withLock {
        try {
            return suspendCancellableCoroutine { continuation ->
                currentRollAction.value = RollActionImpl(
                    roll = roll,
                    continuation = continuation,
                )
            }
        } finally {
            currentRollAction.value = null
        }
    }

    @Stable
    private class RollActionImpl(
        override val roll: RollAction.Uio,
        private val continuation: CancellableContinuation<RollResult>,
    ) : RollAction {
        override fun action(result: RollResult) {
            if (continuation.isActive) continuation.resume(result)
        }
    }
}

@Stable
interface RollResult {

    @Stable
    data class BoundedRollResult(
        val result: Result,
        val difficulty: Difficulty,
    ) : RollResult {
        @Stable
        enum class Result {
            CriticalSuccess,
            SpecialSuccess,
            Success,
            Failure,
            CriticalFailure,
        }

        @Stable
        enum class Difficulty{
            Easy,
            Normal,
            Hard,
            Impossible
        }
    }

    @Stable
    data class BoundlessRollResult(
        val value: Int,
    ) : RollResult

    data object Dismissed: RollResult
}

@Stable
interface RollAction {
    val roll: Uio

    fun action(result: RollResult)

    sealed interface Uio {
        val characterSheetId: String
        val label: String

        @Stable
        data class BoundedRollActionUio(
            override val characterSheetId: String,
            override val label: String,
            val rollAction: String,
            val rollSuccessValue: Int,
        ): Uio

        @Stable
        data class BoundlessRollActionUio(
            override val characterSheetId: String,
            override val label: String,
            val canBeCritical: Boolean,
            val rollDefaultAction: String,
            val rollSpecialAction: String?,
            val rollCriticalAction: String?,
        ): Uio
    }
}