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

import pl.edu.pw.mini.sg.movingtargets._
import com.google.common.collect.ImmutableList
import pl.edu.pw.mini.jk.sg.game.common.{Accident, Cloneable, SecurityGame, TwoPlayerPayoffInfo}
import pl.edu.pw.mini.jk.sg.game.DefenderAttackerGame
import pl.edu.pw.mini.jk.sg.game.immutable.Payoffs

final class MovingTargetsGame(val initialState: MovingTargetsImmutableGame, var state: MovingTargetsImmutableGame, var accidentHistory: List[Accident]) extends DefenderAttackerGame[AttackerDecision, MovingTargetsDefenderMove, MovingTargetsAttackerState, MovingTargetsDefenderState, MovingTargetsImmutableGame] with SecurityGame with Cloneable[MovingTargetsGame] {
  def getAttackerInitialState: MovingTargetsAttackerState = initialState.attackerState
  def getAttackerResult: Double = state.attackerScore
  def getCurrentState: MovingTargetsImmutableGame = state
  def getDefenderInitialState: MovingTargetsDefenderState = initialState.defenderPositions
  def getDefenderResult: Double = state.defenderScore

  var attackerMove : Option[AttackerDecision] = None
  var defenderMove : Option[MovingTargetsDefenderMove] = None

  def finishRound(): TwoPlayerPayoffInfo = {
    (attackerMove, defenderMove) match {
      case (Some(am), Some(dm)) => {
        val (payoffs, newState) = state.makeMoves(dm, am)
        state = newState
        accidentHistory = payoffs match {
          case Payoffs(_,_,0,0) => accidentHistory
          case Payoffs(_,_,n,_) if n > 0 => new Accident(newState.timeStep, 0, -1, true) :: accidentHistory
          case Payoffs(_,_,_,n) if n > 0 => new Accident(newState.timeStep, 0, -1, false) :: accidentHistory
        }
        attackerMove = None
        defenderMove = None
        new TwoPlayerPayoffInfo(payoffs.defenderPayoff, payoffs.attackerPayoff, payoffs.successfulDefenses,payoffs.successfulAttacks)
      }
      case(None, _) => throw new IllegalStateException("Attacker has not moved")
      case(_, None) => throw new IllegalStateException("Defender has not moved")
    }
  }
  def playAttackerMove(move: AttackerDecision): Unit = attackerMove match {
    case None => attackerMove = Some(move)
    case Some(_) => throw new IllegalStateException("Attacker arleady moved!")
  }

  def playDefenderMove(move: MovingTargetsDefenderMove): Unit = defenderMove match {
    case None => defenderMove = Some(move)
    case Some(_) => throw new IllegalStateException("Defender already moved")
  }

  override def getPreviousAccidents: ImmutableList[Accident] = {
    val builder = ImmutableList.builder[Accident]()
    accidentHistory.foreach(builder.add(_))
    builder.build()
  }
  override def accidentOccured : Boolean = !accidentHistory.isEmpty


  override def getTimeStep: Int = state.timeStep

  override def typedClone =new MovingTargetsGame(initialState, state, accidentHistory)
}

