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

import scala.collection.JavaConverters._

import com.google.common.collect.ImmutableList
import pl.edu.pw.mini.jk.sg.game.common.advanceable.AdvanceableAttackerState
import pl.edu.pw.mini.sg.movingtargets.{AttackDecision, AttackerDecision, MovingTargetsGameConfig, WaitDecision}

sealed trait MovingTargetsMultiAttackerState extends AdvanceableAttackerState[AttackerDecision] {
    override def advance(move: AttackerDecision): MovingTargetsMultiAttackerState
}

case class FirstMoveAttackerState(timeStep: Int, defenderCount: Int, possibleMoves: ImmutableList[AttackerDecision]) extends MovingTargetsMultiAttackerState {
  override def advance(move: AttackerDecision): MovingTargetsMultiAttackerState =
    if(!possibleMoves.contains(move))
      throw new IllegalArgumentException("Move not allowed")
    else {
      val newMoves : ImmutableList[AttackerDecision] = move match {
        case AttackDecision(_) => ImmutableList.of(WaitDecision)
        case _ => possibleMoves
      }
      if(defenderCount==1) copy(timeStep = timeStep+1, possibleMoves=newMoves) else NextMoveAttackerState(timeStep, 2, defenderCount, newMoves)
    }

  override def getPossibleMoves(): ImmutableList[AttackerDecision] = possibleMoves
  
  override def getTimeStep = timeStep
}

case class NextMoveAttackerState(timeStep: Int, currentMove: Int, defenderCount: Int, possibleMoves: ImmutableList[AttackerDecision]) extends MovingTargetsMultiAttackerState {
  override def advance(move: AttackerDecision): MovingTargetsMultiAttackerState = move match {
    case WaitDecision => if(currentMove == defenderCount) FirstMoveAttackerState(timeStep+1, defenderCount, possibleMoves) else copy(currentMove = currentMove+1)
    case _ => throw new IllegalArgumentException("Move not allowed");
  }
  override def getPossibleMoves(): ImmutableList[AttackerDecision] = ImmutableList.of(WaitDecision)
  
  override def getTimeStep = timeStep
}


object MovingTargetsMultiAttackerState {
  def initialState(gameConfig: MovingTargetsGameConfig) = {
    val possibleMoves = ImmutableList.copyOf[AttackerDecision](asJavaIterableConverter(WaitDecision :: gameConfig.targets.map(t => AttackDecision.apply(t.id))).asJava)
    FirstMoveAttackerState(0, gameConfig.defenderCount, possibleMoves)
  }
}
