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

import pl.edu.pw.mini.jk.lib.TimedExecution
import pl.edu.pw.mini.jk.sg.game.immutable.mutable.MutableWrapper
import pl.edu.pw.mini.jk.sg.game.{ GameVariantRunner, GameVariantRunnerResult, NormalizableFactoryAction }
import pl.edu.pw.mini.sg.movingtargets.MovingTargetsAttackerState
import pl.edu.pw.mini.sg.movingtargets.{ AttackerDecision, MovingTargetsGameConfig }



final case class AggregateGameVariantRunner(
  config: MovingTargetsGameConfig,
  aggregation: Int
) extends GameVariantRunner {
  override def runWithSingleMovePerTimestepFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] = runWithRealFactory(action)
  override def runWithMultiMovePerTimestepFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] = runWithRealFactory(action)
  override def runWithCoordGameFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] = runWithRealFactory(action)
  override def runWithCompactGameFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] = runWithRealFactory(action)

  def runWithRealFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] = {
    val (factory, time) = TimedExecution(new AggregatedNormalizableFactory(config, aggregation))
    val result = action.runWithNormalizableFactory[
      AttackerDecision,
      AggregateMTGDefenderMove,
      MovingTargetsAttackerState,
      AggregateMTGDefenderState,
      MutableWrapper[
        AttackerDecision,
        AggregateMTGDefenderMove,
        MovingTargetsAttackerState,
        AggregateMTGDefenderState,
        AggregateMovingTargetsGame
      ]
    ](factory, config.roundLimit)
  GameVariantRunnerResult(result, time)
  }
}
