package pl.edu.pw.mini.game.search

import java.util.UUID

import org.scalatest.{Matchers, WordSpec}
import pl.edu.pw.mini.sg.game.graph.{Edge, GraphConfig}

class SearchGameSpec extends WordSpec with Matchers {
  val config = SearchGameConfig(
    GraphConfig(7, List(Edge(5, 1), Edge(5, 2), Edge(6, 1),Edge(6, 2), Edge(6, 3), Edge(1, 1), Edge(2, 2), Edge(3, 3) ,Edge(0, 1), Edge(0, 2), Edge(0, 3), Edge(1, 2), Edge(2, 1), Edge(2, 3), Edge(1, 4), Edge(2, 4), Edge(3, 4)).toVector),
    5, 2, 0, Vector(5, 6), List(SearchGameTarget(4, 1.3)), List(List(1, 2, 5), List(1, 2, 3, 6)), List(1,2,3), coveringUpTracksPossible = true,
    UUID.fromString("658f740c-8c22-473f-8d6f-5cbea8c10f3d"))

  "The SearchGame class" should {
    val game = SearchGame(config)
    "define a makeMove method" which {
      "returns finished game when attacker is caught in vertex" in {
        val newGame = game.makeMove(List(1, 3), SearchGameAttackerMove(1))
        newGame should be ('leaf)
      }

      "returns finished game when attacker is caught on edge" in {
        val newGame = game.makeMove(List(1, 3), SearchGameAttackerMove(2))
                          .makeMove(List(2, 3), SearchGameAttackerMove(1))

        newGame should be ('leaf)
      }

      "returns finished game when attacker gets to target" in {
        val newGame = game.makeMove(List(1, 3), SearchGameAttackerMove(2))
          .makeMove(List(2, 3), SearchGameAttackerMove(4))
        newGame should be ('leaf)
      }

      "returns game in progress otherwise" in {
        val newGame = game.makeMove(List(1, 3), SearchGameAttackerMove(2))
        newGame should not be 'leaf
      }
    }

    "define attacker payoff" which {
      "returns 0 for game in progress" in {
        val payoff = game.makeMove(List(1, 3), SearchGameAttackerMove(2)).attackerPayoff
        payoff should equal(0)
      }

      "returns 0 for inconclusive game" in {
        val newGame = game.makeMove(List(1, 3), SearchGameAttackerMove(2))
          .makeMove(List(1, 3), SearchGameAttackerMove(2))
          .makeMove(List(1, 3), SearchGameAttackerMove(2))
          .makeMove(List(1, 3), SearchGameAttackerMove(2))
          .makeMove(List(1, 3), SearchGameAttackerMove(2))
        val payoff = newGame.attackerPayoff
        newGame should be ('leaf)
        payoff should equal(0)
      }

      "returns defined payoff when attacker is first on target" in {
        val payoff = game.makeMove(List(1, 3), SearchGameAttackerMove(2))
          .makeMove(List(2, 3), SearchGameAttackerMove(4)).attackerPayoff
        payoff should equal(1.3)
      }

      "returns -1 when attacker gets caught in vertex" in {
        val payoff = game.makeMove(List(1, 3), SearchGameAttackerMove(1)).attackerPayoff
        payoff should equal(-1)
      }

      "return -1 when attacker gets caught on edge" in {
        val payoff = game.makeMove(List(1, 3), SearchGameAttackerMove(2))
                         .makeMove(List(2, 3), SearchGameAttackerMove(1)).attackerPayoff

        payoff should equal(-1)
      }

      "returns -1 when attacker gets caught on target" in {
        val payoff = game.makeMove(List(1, 3), SearchGameAttackerMove(2))
          .makeMove(List(4, 3), SearchGameAttackerMove(4)).attackerPayoff
        payoff should equal(-1)
      }
    }
  }
}
