package pl.edu.pw.mini.sg.game.graph.sud

import pl.edu.pw.mini.sg.game.deterministic.DeterministicGame
import pl.edu.pw.mini.sg.game.graph.DeterministicGraphGameConfig


final case class DeterministicSingleUnitMoveGraphGame(
  defenderState : SingleUnitDefenderState,
  attackerState : SingleUnitAttackerState
) extends DeterministicGame[
  Int, Int, SingleUnitDefenderState,
  SingleUnitAttackerState,
  DeterministicSingleUnitMoveGraphGame
] {
  import DeterministicSingleUnitMoveGraphGame.NEUTRAL_PAYOFF
  override val (defenderPayoff, attackerPayoff): (Double, Double) = {
    if(defenderState.timeStep >= defenderState.graphGameConfig.rounds) {
      if(defenderState.unitPositions.contains(attackerState.attackerPosition))
        (
          defenderState.graphGameConfig.vertexDefenderRewards(attackerState.attackerPosition),
          defenderState.graphGameConfig.vertexAttackerPenalties(attackerState.attackerPosition)
        )
      else if(attackerState.gameConfig.targets.contains(attackerState.attackerPosition)) {
        val target = attackerState.gameConfig.targets.indexOf(attackerState.attackerPosition)
        (
          attackerState.gameConfig.targetDefenderPenalties(target),
          attackerState.gameConfig.targetAttackerRewards(target)
        )
      } else
        (NEUTRAL_PAYOFF, NEUTRAL_PAYOFF)
    } else
      (NEUTRAL_PAYOFF,NEUTRAL_PAYOFF)

  }
  override def makeMove(defenderMove: Int, attackerMove: Int): DeterministicSingleUnitMoveGraphGame = {
    val nextDefender = defenderState.continuation(defenderMove)
    val nextAttacker = attackerState.continuation(attackerMove)

    if(nextDefender.currentUnit == 0 &&
      (nextDefender.unitPositions.contains(nextAttacker.attackerPosition) ||
      nextDefender.graphGameConfig.targets.contains(nextAttacker.attackerPosition))){
      DeterministicSingleUnitMoveGraphGame(
        SingleUnitDefenderState(graphGameConfig = nextDefender.graphGameConfig,
          unitPositions = nextDefender.unitPositions,
          currentUnit = nextDefender.currentUnit,
          timeStep = defenderState.graphGameConfig.rounds
        ),
        new SingleUnitAttackerState(gameConfig = nextAttacker.gameConfig, attackerPosition = nextAttacker.attackerPosition, timeStep = attackerState.gameConfig.rounds, complementaryDefender = 0)
      )
    } else {
      DeterministicSingleUnitMoveGraphGame(nextDefender, nextAttacker)
    }
  }
}

object DeterministicSingleUnitMoveGraphGame {
  final val NEUTRAL_PAYOFF=0.0

  def apply(gameConfig: DeterministicGraphGameConfig) : DeterministicSingleUnitMoveGraphGame = {
    apply(
      gameConfig.initialDefenderState,
      gameConfig.initialAttackerState
    )
  }
}

