package ch.dissem.yaep.domain

import ch.dissem.yaep.domain.Animal.ANT
import ch.dissem.yaep.domain.Animal.OCTOPUS
import ch.dissem.yaep.domain.Animal.SNAIL
import ch.dissem.yaep.domain.Nationality.CANADA
import ch.dissem.yaep.domain.Nationality.SWITZERLAND
import ch.dissem.yaep.domain.Nationality.UKRAINE
import ch.dissem.yaep.domain.Profession.ASTRONAUT
import ch.dissem.yaep.domain.Profession.FARMER
import ch.dissem.yaep.domain.Profession.SOFTWARE_DEV
import ch.tutteli.atrium.api.fluent.en_GB.feature
import ch.tutteli.atrium.api.fluent.en_GB.toBeLessThan
import ch.tutteli.atrium.api.fluent.en_GB.toEqual
import ch.tutteli.atrium.api.verbs.expect
import kotlin.test.Test

class GameTest {

    @Test
    fun `ensure generated game is valid`() {
        val game = generateGame()
        expect(game) {
            feature(Game::areCategoriesValid).toEqual(true)
            feature(Game::areRulesViolated).toEqual(false)
            feature(Game::clues) {
                feature(List<Clue>::size).toBeLessThan(30)
            }
        }
    }

    @Test
    fun `ensure game can be solved`() {
        val professions = listOf(
            Item(ASTRONAUT),
            Item(FARMER),
            Item(SOFTWARE_DEV)
        )
        val animals = listOf(
            Item(SNAIL),
            Item(ANT),
            Item(OCTOPUS)
        )
        val nationalities = listOf(
            Item(UKRAINE),
            Item(CANADA),
            Item(SWITZERLAND)
        )
        val game = Game(
            Grid(listOf(
                GameRow(
                    Profession,
                    professions,
                    professions.map { GameCell(null, it, professions.toMutableList()) }
                ),
                GameRow(
                    Animal,
                    animals,
                    animals.map { GameCell(null, it, animals.toMutableList()) }
                ),
                GameRow(
                    Nationality,
                    nationalities,
                    nationalities.map { GameCell(null, it, nationalities.toMutableList()) }
                )
            )),
            listOf(
                TripletClue(professions[0], animals[1], nationalities[2]),
                OrderClue(professions[0], nationalities[1]),
                SameColumnClue(animals[1], nationalities[1]),
                NeighbourClue(professions[0], professions[1]),
                PositionClue(animals[0], 0)
            )
        )

        expect(solve(game.grid, game.clues)).toEqual(PuzzleSolution.SOLVABLE)
    }

}