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

import androidx.compose.ui.focus.FocusState
import ch.tutteli.atrium.api.fluent.en_GB.notToEqual
import ch.tutteli.atrium.api.fluent.en_GB.toEqual
import ch.tutteli.atrium.api.verbs.expect
import kotlin.test.Test

class FocusFollowingSelectionManagerTest :
    SelectionManagerTest<FocusFollowingFocusable, FocusFollowingSelectionManager>() {

    var focusables = mutableListOf<FocusFollowingFocusable>()

    val active = object : FocusState {
        override val isFocused: Boolean = true
        override val hasFocus: Boolean = true
        override val isCaptured: Boolean = true
    }
    val inactive = object : FocusState {
        override val isFocused: Boolean = false
        override val hasFocus: Boolean = false
        override val isCaptured: Boolean = false
    }

    override fun setUp() {
        manager = FocusFollowingSelectionManager
        manager.focused = null

        focusables = mutableListOf()
        repeat(4) {
            focusables.add(manager.add())
        }
    }

    @Test
    fun ensure_focus_is_followed() {
        expect(manager.focused).toEqual(null)
        for (focusable in focusables) {
            expect(manager.focused).notToEqual(focusable)
            focusable.setFocus(active)
            expect(manager.focused).toEqual(focusable)
        }
    }

    @Test
    fun ensure_focus_is_lost_when_same_focusable_is_set_inactive() {
        for (focusable in focusables) {
            focusable.setFocus(active)
            expect(manager.focused).toEqual(focusable)
            focusable.setFocus(inactive)
            expect(manager.focused).toEqual(null)
        }
    }

    @Test
    fun ensure_focus_is_not_lost_if_different_focusable_is_set_inactive() {
        var lastFocused: FocusFollowingFocusable? = null
        for (focusable in focusables) {
            focusable.setFocus(inactive)
            expect(manager.focused).toEqual(lastFocused)
            focusable.setFocus(active)
            expect(manager.focused).toEqual(focusable)
            lastFocused = focusable
        }
        expect(manager.focused).toEqual(lastFocused)
    }
}