package pl.edu.pw.mini.sg.movingtargets.coverage

import canes.game.{ Depot, Target, MovingTargetsGame }
import java.util.UUID
import org.scalatest._
import pl.edu.pw.mini.jk.sg.game.immutable.Payoffs
import pl.edu.pw.mini.sg.movingtargets.{ AttackDecision, MovingTargetsGameConfig, WaitDecision }
import scala.collection.immutable.SortedSet

class CoverageImmutableGameSpec extends WordSpec with Matchers {
  "CoordImmutableGame" when {
    "playing game with single round attack" should {
      val gameConfig = MovingTargetsGameConfig(MovingTargetsGame(UUID.fromString("123e4567-e89b-12d3-a456-426655440000"),
        List(Depot(1, 5, 5), Depot(2,8,8)),
        List(Target(1, 1, 2, List(2,33,50), 10, -5, -8, 4)),
        0.5, 2, 2, List(1,1), 1, 3, 1, 0), 1)

      val game = CoverageImmutableGame.initialState(gameConfig)

      val fin = game.makeMoves(CoverageDefenderMove(SortedSet()), AttackDecision(1))
      val finp = game.makeMoves(CoverageDefenderMove(SortedSet(1)), AttackDecision(1))


      "give attacker reward when round finished" in {
        fin._1.shouldEqual(Payoffs(-8, 10, 1, 0))
      }

      "give defender reward when protecting" in {
        finp._1.shouldEqual(Payoffs(4,-5,0,1))
      }

      "clear attack started after succeed" in {
        fin._2.attackStarted shouldEqual(None)
      }

      "clear attack started after failed" in {
        finp._2.attackStarted shouldEqual(None)
      }
    }

    "playing game with three round attack" should {
      val gameConfig = MovingTargetsGameConfig(MovingTargetsGame(UUID.fromString("123e4567-e89b-12d3-a456-426655440000"),
        List(Depot(1, 5, 5), Depot(2,8,8)),
        List(Target(1, 1, 2, List(2,33,50), 10, -5, -8, 4)),
        0.5, 2, 2, List(1,1), 1, 3, 1, 2), 1)

      val game = CoverageImmutableGame.initialState(gameConfig)

      val firstNoProt = game.makeMoves(CoverageDefenderMove(SortedSet()), AttackDecision(1))
      val secondNoProt = firstNoProt._2.makeMoves(CoverageDefenderMove(SortedSet()), WaitDecision)
      val thirdNoProt = secondNoProt._2.makeMoves(CoverageDefenderMove(SortedSet()), WaitDecision)

      "not give payoffs after first two unprotected rounds" in {
        firstNoProt._1 shouldEqual(Payoffs(0,0,0,0))
        secondNoProt._1 shouldEqual(Payoffs(0,0,0,0))
      }

      "not contain target 1 in protection in third unprotected round" in {
        thirdNoProt._2.defenderState.coveredTargets shouldBe empty
      }

      "give attacker reward in third unprotected round" in {
        thirdNoProt._1 shouldEqual(Payoffs(-8, 10, 1, 0))
      }

      val firstProt = game.makeMoves(CoverageDefenderMove(SortedSet(1)), AttackDecision(1))
      val secondProt = firstNoProt._2.makeMoves(CoverageDefenderMove(SortedSet(1)), WaitDecision)
      val thirdProt = secondNoProt._2.makeMoves(CoverageDefenderMove(SortedSet(1)), WaitDecision)

      "give defender reward when protected in third round" in {
        thirdProt._1.shouldEqual(Payoffs(4,-5,0,1))
      }

      "give defender reward when protected in second round" in {
        secondProt._1.shouldEqual(Payoffs(4,-5,0,1))
      }

      "give defender reward when protected in first round" in {
        firstProt._1.shouldEqual(Payoffs(4,-5,0,1))
      }

      "clear attackStarted after success" in {
        thirdNoProt._2.attackStarted shouldEqual(None)
      }

      "clear attackStarted after failure" in {
        thirdProt._2.attackStarted.shouldEqual(None)
        secondProt._2.attackStarted shouldEqual(None)
        firstProt._2.attackStarted shouldEqual(None)
      }

    }

  }
}
