package ch.dissem.yaep.domain

import ch.dissem.yaep.domain.PuzzleSolution.SOLVABLE
import ch.tutteli.atrium.api.fluent.en_GB.toBeEmpty
import ch.tutteli.atrium.api.fluent.en_GB.toEqual
import ch.tutteli.atrium.api.verbs.expect
import kotlin.test.Test
import kotlin.time.ExperimentalTime

class GameSolverTest {

    @Test
    @OptIn(ExperimentalTime::class)
    fun `ensure there are no unnecessary clues`() {
        var game: Game
        var neighbours: List<NeighbourClue<*, *>>
        repeat(10) {
            game = generateGame()
            val triplets = game.horizontalClues.filterIsInstance<TripletClue<*, *, *>>()
            neighbours = game.horizontalClues.filterIsInstance<NeighbourClue<*, *>>()
                .filter { n ->
                    triplets.any { t ->
                        t.contains(n.a) && t.contains(n.b)
                    }
                }
            expect(neighbours).toBeEmpty()
            expect(game.solve()).toEqual(SOLVABLE)
        }
    }

    fun TripletClue<*, *, *>.contains(item: Item<*>): Boolean {
        return this.a.itemType == item.itemType || this.b.itemType == item.itemType || this.c.itemType == item.itemType
    }

    @Test
    fun `ensure game can be solved`() {
        val gameString = this::class.java.getResourceAsStream("/games/001.yaep")!!
            .bufferedReader()
            .readText()
        val game = Game.parse(gameString)

        val solution = game.solve()

        expect(solution).toEqual(SOLVABLE)
    }

}
