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

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


class MovingTargetsMultiMutableGame(private var state: MovingTargetsMultiImmutableGame, initialState: MovingTargetsMultiImmutableGame, private var accidentHistory: List[Accident], private var defenderPayoff: Double, private var attackerPayoff: Double)
    extends SecurityGame with Cloneable[MovingTargetsMultiMutableGame] with
    DefenderAttackerGame[AttackerDecision, MovingTargetsDefenderMoveMulti, MovingTargetsMultiAttackerState, MovingTargetsDefenderStateMulti, MovingTargetsMultiImmutableGame]
{
  private var defenderMove : Option[MovingTargetsDefenderMoveMulti] = None
  private var attackerMove : Option[AttackerDecision] = None
  
  // Members declared in pl.edu.pw.mini.jk.sg.game.graph.advanceable.DefenderAttackerGame
  override def finishRound(): TwoPlayerPayoffInfo = (defenderMove, attackerMove) match {
    case (None, _) => throw new IllegalStateException("Defender has not moved")
    case (_, None) => throw new IllegalStateException("Attacker has not moved")
    case (Some(dm), Some(am)) => {
      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)
    }
  }
  override def getAttackerInitialState: MovingTargetsMultiAttackerState = initialState.attackerState
  override def getAttackerResult: Double = attackerPayoff
  override def getCurrentState: MovingTargetsMultiImmutableGame = state
  override def getDefenderInitialState: MovingTargetsDefenderStateMulti = initialState.defenderState
  override def getDefenderResult: Double = defenderPayoff
  override def playAttackerMove(move: AttackerDecision): Unit = attackerMove match {
    case None => attackerMove = Some(move)
    case _ => throw new IllegalStateException("attacker already moved")
  }
  override def playDefenderMove(move: MovingTargetsDefenderMoveMulti): Unit = defenderMove match {
    case None => defenderMove = Some(move)
    case _ => throw new IllegalStateException("attacker already moved")
  }
  
  // Members declared in pl.edu.pw.mini.jk.sg.game.common.SecurityGame
  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: MovingTargetsMultiMutableGame = new MovingTargetsMultiMutableGame(state, initialState, accidentHistory, defenderPayoff, attackerPayoff)
}
