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

import pl.edu.pw.mini.jk.sg.game.immutable.{ ImmutableGame, Payoffs }
import pl.edu.pw.mini.sg.movingtargets.{ AttackDecision, AttackStart, AttackerDecision, MovingTargetsAttackerState, MovingTargetsGameConfig }


final case class CoverageImmutableGame(
  defenderState: CoverageDefenderStateCached,
  attackerState: MovingTargetsAttackerState,
  defenderPayoff: Double,
  attackerPayoff: Double,
  attackStarted: Option[AttackStart],
  gameConfig: MovingTargetsGameConfig,
  positionHelper: CoveragePositionsHelper
) extends ImmutableGame[
  CoverageDefenderMove,
  AttackerDecision,
  CoverageDefenderStateCached,
  MovingTargetsAttackerState,
  CoverageImmutableGame
] {

  override def attackerVisibleState: MovingTargetsAttackerState = attackerState
  override def defenderVisibleState: CoverageDefenderStateCached = defenderState
  override def makeMoves(defenderMove: CoverageDefenderMove,attackerMove: AttackerDecision): (Payoffs, CoverageImmutableGame) = {
    val newDefenderState = defenderState.advance(defenderMove)
    val newAttackerState = attackerState.advance(attackerMove)
    val (newAttackStarted, payoffs) = (attackerMove match {
      case AttackDecision(targetId) => Some(AttackStart(newDefenderState.timeStep, targetId))
      case _ => this.attackStarted
    }) match {
      case as@Some(AttackStart(timeStep, targetId)) => {
        lazy val target = gameConfig.getTargetById(targetId)
        if(newDefenderState.coveredTargets.contains(targetId))
          (None, Payoffs(target.defenderUtilityUnuccessfulAttack, target.attackerUtilityUnuccessfulAttack, 0, 1))
        else if(timeStep + gameConfig.attackLength == newDefenderState.timeStep)
          (None, Payoffs(target.defenderUtilitySuccessfulAttack, target.attackerUtilitySuccessfulAttack, 1, 0))
        else
          (as, Payoffs(0,0,0,0))
      }
      case None => (None, Payoffs(0, 0, 0, 0))
    }

    (payoffs, CoverageImmutableGame(newDefenderState, newAttackerState, defenderPayoff + payoffs.defenderPayoff, attackerPayoff+payoffs.attackerPayoff, newAttackStarted, gameConfig, positionHelper))
  }
  override def timeStep: Int = defenderState.timeStep
}


object CoverageImmutableGame {
  def initialState(gameConfig: MovingTargetsGameConfig) = {
    val (cachedTree, helper) = CoverageDefenderStateCached.generateStateTree(gameConfig)
    CoverageImmutableGame(cachedTree, MovingTargetsAttackerState.createState(false, gameConfig.targets.map(_.id)), 0, 0, None, gameConfig, helper)
  }
}
