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

import com.google.common.collect.ImmutableList
import pl.edu.pw.mini.jk.sg.game.common.advanceable.AdvanceableAttackerState
import pl.edu.pw.mini.jk.sg.game.immutable.AdvanceableState
import pl.edu.pw.mini.sg.movingtargets.MovingTargetsGameConfig

import collection.JavaConverters._

sealed trait CoordAttackerState extends AdvanceableAttackerState[CoordAttackerMove] with AdvanceableState[CoordAttackerMove, CoordAttackerState] {
}

object CoordAttackerState {
  def initialState(game: MovingTargetsGameConfig) = {
    CoordAttackerMoveState(
      0,
      false,
      ImmutableList.copyOf((WaitDecision :: game.targets.map(t => AttackDecision(t.id))).asJava.asInstanceOf[java.lang.Iterable[CoordAttackerMove]]),
      game
    )
  }
}

case class CoordAttackerMoveState(
  timeStep: Int,
  hasAttacked: Boolean,
  possibleMoves: ImmutableList[CoordAttackerMove],
  game: MovingTargetsGameConfig
) extends CoordAttackerState {
  override def advance(move: CoordAttackerMove): CoordAttackerSkipState =
    move match {
      case WaitDecision => CoordAttackerSkipState(timeStep, hasAttacked, possibleMoves, game, 0)
      case AttackDecision(targetId) if !hasAttacked && game.targets.map(_.id).contains(targetId) => CoordAttackerSkipState(timeStep, true, possibleMoves, game, 0)
      case _ => throw new IllegalArgumentException("Move not allowed in current state")
    }
  override def getPossibleMoves(): ImmutableList[CoordAttackerMove] =
    if(hasAttacked)
      WaitDecision.asList
    else
      possibleMoves

  override def getTimeStep = timeStep
}

case class CoordAttackerSkipState(
  timeStep: Int,
  hasAttacked: Boolean,
  possibleMoves: ImmutableList[CoordAttackerMove],
  game: MovingTargetsGameConfig,
  skippedTurns: Int
) extends CoordAttackerState {
  override def advance(move: CoordAttackerMove): CoordAttackerState =
    move match {
      case DummyMove =>
        if(skippedTurns+1 == game.defenderCount * 2 -1)
          CoordAttackerMoveState(timeStep+1, hasAttacked, possibleMoves, game)
        else
          copy(skippedTurns = skippedTurns + 1)
      case _ =>
        throw new IllegalArgumentException("Move not allowed in state")
    }

  override def getPossibleMoves(): ImmutableList[CoordAttackerMove] = DummyMove.asList

  override def getTimeStep = timeStep
}
