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

import java.util.UUID
import org.scalatest._
import canes.game.{Depot, Target, MovingTargetsGame}
import pl.edu.pw.mini.sg.movingtargets.{DefenderPosition, MovingTargetsGameConfig}

import collection.JavaConverters._

class CoordDefenderStateSpec extends WordSpec with Matchers {
  "CoordDefenderState with game has two bases" when {
    val gameConfig = MovingTargetsGameConfig(MovingTargetsGame(
      UUID.fromString("123e4567-e89b-12d3-a456-426655440000"),
      List(Depot(1, 5, 5), Depot(2, 20, 20)),
      List(Target(1, 1, 2, List(2, 33, 50), 10, -5, -8, 4)),
      0.5, 2, 2, List(1, 1), 1, 100, 1, 0
    ), 1)

    val state = CoordDefenderState.initialState(gameConfig)

    "initial state" should {

      "allow three second defender x coords" in {
        state.getPossibleMoves.asScala should contain only (XMove(0), XMove(1), XMove(2))
      }

      "throw illegal argument exception when playing ymove first" in {
        an[IllegalArgumentException] shouldBe thrownBy(state.advance(YMove(0)))
      }

      "throw illegal argument exception when playing xmove too far away" in {
        an[IllegalArgumentException] shouldBe thrownBy(state.advance(XMove(4)))
        an[IllegalArgumentException] shouldBe thrownBy(state.advance(XMove(-4)))
      }

      "allow three second defender y coords after moving to x=0" in {
        state.advance(XMove(0)).getPossibleMoves.asScala should contain only (YMove(0), YMove(1), YMove(2))
      }

      "have timestep=0 after two moves" in {
        state.advance(XMove(0)).advance(YMove(0)).timeStep should be(0)
      }

      "allow three second defender x moves" in {
        state.advance(XMove(0)).advance(YMove(1)).getPossibleMoves.asScala should contain only (XMove(0), XMove(1), XMove(2))
      }

      "allow one y move after moving x=2" in {
        state.advance(XMove(2)).getPossibleMoves should contain only (YMove(0))

        an[IllegalArgumentException] shouldBe thrownBy(state.advance(XMove(2)).advance(YMove(-1)))
      }
    }

    "move sequence 2,0,0,2 was performed" should {
      val newState = state.advance(XMove(2)).advance(YMove(0)).advance(XMove(0)).advance(YMove(2))

      "have timestep=1" in { newState.timeStep should be(1) }
      "allow 5 x moves for first defender" in {
        newState.getPossibleMoves.asScala should contain only (XMove(0), XMove(1), XMove(2), XMove(3), XMove(4))
      }
      "have current positions (0,2),(2,0)" in {
        newState.currentPositions should be(Vector(DefenderPosition(2, 0), DefenderPosition(0, 2)))
      }
    }
  }
}
