package ch.dissem.yaep.domain

import ch.tutteli.atrium.api.fluent.en_GB.toEqual
import ch.tutteli.atrium.api.verbs.expect
import kotlin.test.Test

class SameColumnClueTest : ClueTest() {
    @Test
    fun `ensure fields in the same column are considered valid`() {
        val grid = createGrid()
        for (ia in 0 until size - 1) {
            for (ib in ia + 1 until size) {
                for (j in 0 until size) {
                    val a = grid[ia][j]
                    val b = grid[ib][j]

                    a.solution!!
                    b.solution!!

                    expect(SameColumnClue(a.solution, b.solution).isValid(grid)).toEqual(true)
                    expect(SameColumnClue(b.solution, a.solution).isValid(grid)).toEqual(true)
                }
            }
        }

    }

    @Test
    fun `ensure fields in different columns are considered invalid`() {
        val grid = createGrid()
        for (ia in 0 until size - 1) {
            for (ib in ia + 1 until size) {
                for (ja in 0 until size - 1) {
                    for (jb in ja + 1 until size) {
                        val a = grid[ia][ja]
                        val b = grid[ib][jb]

                        a.solution!!
                        b.solution!!

                        expect(SameColumnClue(a.solution, b.solution).isValid(grid)).toEqual(false)
                        expect(SameColumnClue(b.solution, a.solution).isValid(grid)).toEqual(false)
                    }
                }
            }
        }
    }

    @Test
    fun `if a is set, but b is set to a wrong value, it's considered invalid`() {
        val grid = createGrid { null }

        for (ia in 0 until size - 1) {
            for (ib in ia + 1 until size) {
                for (ja in 0 until size - 1) {
                    for (jb in ja + 1 until size) {
                        val a = grid[ia][ja]
                        val b = grid[ib][jb]

                        a.solution!!
                        b.solution!!

                        a.selection = a.solution
                        b.selection = b.solution

                        expect(SameColumnClue(a.solution, b.solution).isValid(grid)).toEqual(false)
                        expect(SameColumnClue(b.solution, a.solution).isValid(grid)).toEqual(false)
                    }
                }
            }
        }
    }

    @Test
    fun `if there are no options for a and b in the same column, it's considered invalid`() {
        val grid = createGrid { null }

        val rowA = grid.random()
        val rowB = grid.filter { it != rowA }.random()

        for (i in 0 until size) {
            val a = rowA[i]
            val b = rowB[i]

            a.solution!!
            b.solution!!

            rowA.forEachIndexed { index, gameCell ->
                if (index < i) {
                    gameCell.selection = rowA.options.filter { it != a.solution }.random()
                } else {
                    gameCell.selection = null
                }
            }
            rowB.forEachIndexed { index, gameCell ->
                if (index < i) {
                    gameCell.selection = null
                } else {
                    gameCell.selection = rowB.options.filter { it != b.solution }.random()
                }
            }

            expect(SameColumnClue(a.solution, b.solution).isValid(grid)).toEqual(false)
            expect(SameColumnClue(b.solution, a.solution).isValid(grid)).toEqual(false)
        }
    }
}
