package pl.edu.pw.mini.sg.efgame

import pl.edu.pw.mini.sg.game.deterministic.json.DeterministicGameJson
import pl.edu.pw.mini.sg.game.deterministic.plugin.GameFactory


object EfGameFactory extends GameFactory[EfGameConfig] {
  override type DefenderMove = Int
  override type AttackerMove = Int
  override type DefenderState = EfDefenderState
  override type AttackerState = EfAttackerState
  override type Game = EfGame

  override def create(gameConfig: EfGameConfig) : EfGame = new EfGameInner(gameConfig.gameTree, gameConfig)
  override val json: DeterministicGameJson[DefenderMove, AttackerMove, DefenderState, AttackerState] = EfGameJson

  def maxDefenderPayoff(gameConfig: EfGameConfig): Double = maxPayoff(gameConfig.gameTree)
  def minDefenderPayoff(gameConfig: EfGameConfig): Double = minPayoff(gameConfig.gameTree)
  def maxAttackerPayoff(gameConfig: EfGameConfig): Double = maxAPayoff(gameConfig.gameTree)
  def minAttackerPayoff(gameConfig: EfGameConfig): Double = minAPayoff(gameConfig.gameTree)


  private def maxPayoff(tree: GameNode) : Double = tree match {
    case InnerGameNode(_, _, successors) => successors.values.flatMap(_.values).map(maxPayoff).max
    case LeafGameNode(dp, ap) => dp
  }
  private def minPayoff(tree: GameNode) : Double = tree match {
    case InnerGameNode(_, _, successors) => successors.values.flatMap(_.values).map(minPayoff).min
    case LeafGameNode(dp, ap) => dp
  }

  private def maxAPayoff(tree: GameNode) : Double = tree match {
    case InnerGameNode(_, _, successors) => successors.values.flatMap(_.values).map(maxPayoff).max
    case LeafGameNode(dp, ap) => ap
  }
  private def minAPayoff(tree: GameNode) : Double = tree match {
    case InnerGameNode(_, _, successors) => successors.values.flatMap(_.values).map(minPayoff).min
    case LeafGameNode(dp, ap) => ap
  }

}
