package ch.dissem.yaep.ui.common.focus

import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import kotlinx.coroutines.flow.MutableStateFlow

abstract class SelectionManager<F : Focusable<F>> {
    var isActiveFlow = MutableStateFlow<Boolean>(false)
    var isActive: Boolean
        get() = isActiveFlow.value
        set(value) {
            isActiveFlow.value = value
        }

    var focusedFlow = MutableStateFlow<F?>(null)

    var focused: F?
        get() = focusedFlow.value
        set(value) {
            val previous = focusedFlow.value
            if (previous != value) {
                previous?.child?.isActive = false
                value?.child?.isActive = true
                focusedFlow.value = value
            }
        }

    fun add(): F = add(null, null)

    fun add(primaryAction: () -> Unit): F = add(primaryAction, null)

    abstract fun add(
        primaryAction: (() -> Unit)?,
        secondaryAction: (() -> Unit)?
    ): F

    fun onKeyEvent(event: KeyEvent): Boolean {
        if (event.type != KeyEventType.KeyUp) return false

        return when (event.key) {
            Key.Spacebar, Key.Enter -> {
                focused?.primaryAction?.invoke() != null ||
                        focused?.onKeyEvent?.invoke(event) == true ||
                        focused?.child?.onKeyEvent(event) == true
            }

            Key.Delete, Key.Backspace -> {
                focused?.secondaryAction?.invoke() != null ||
                        focused?.onKeyEvent?.invoke(event) == true ||
                        focused?.child?.onKeyEvent(event) == true
            }

            else -> focused?.onKeyEvent?.invoke(event) == true || doOnKeyEvent(event)
        }
    }

    protected abstract fun doOnKeyEvent(event: KeyEvent): Boolean
}