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

import pl.edu.pw.mini.jk.sg.game.immutable.mutable.MutableWrapper
import pl.edu.pw.mini.jk.sg.game.{ GameVariantRunner, NormalizableFactoryAction, GameVariantRunnerResult }
import pl.edu.pw.mini.sg.movingtargets.coord.{ CoordAttackerMove, CoordAttackerState, CoordDefenderState, CoordImmutableGame, CoordMove, CoordNormalizableFactory }
import pl.edu.pw.mini.sg.movingtargets.coverage.{ CoverageDefenderMove, CoverageDefenderStateCached, CoverageImmutableGame, CoverageNormalizableFactory }
import pl.edu.pw.mini.sg.movingtargets.multi.{ MovingTargetsDefenderMoveMulti, MovingTargetsDefenderStateMulti, MovingTargetsMultiAttackerState, MovingTargetsMultiMutableGame, MovingTargetsMultiMutableGameFactory }
import pl.edu.pw.mini.sg.movingtargets.mutable.{ MovingTargetsGame, MovingTargetsGameFactory }

import pl.edu.pw.mini.jk.lib.TimedExecution



case class MovingTargetsVariantRunner(config: MovingTargetsGameConfig)
 extends GameVariantRunner{
  override def runWithSingleMovePerTimestepFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] =
{
  val (factory, time) = TimedExecution(MovingTargetsGameFactory(config))
    val result = action.runWithNormalizableFactory[
      AttackerDecision, 
      MovingTargetsDefenderMove,
      MovingTargetsAttackerState,
      MovingTargetsDefenderState,
      MovingTargetsGame
    ](factory, config.roundLimit)
  GameVariantRunnerResult(result, time)
  }
  override def runWithMultiMovePerTimestepFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] = {
    val (factory, time) = TimedExecution(MovingTargetsMultiMutableGameFactory(config))
    val result = action.runWithNormalizableFactory[
      AttackerDecision,
      MovingTargetsDefenderMoveMulti,
      MovingTargetsMultiAttackerState,
      MovingTargetsDefenderStateMulti,
      MovingTargetsMultiMutableGame
    ](
      factory,
      config.roundLimit
    )
    GameVariantRunnerResult(result, time)
  }
  override def runWithCoordGameFactory[R](action: NormalizableFactoryAction[R]) : GameVariantRunnerResult[R] = {
    val (factory, time) = TimedExecution(new CoordNormalizableFactory(config))
    val result = action.runWithNormalizableFactory[
      CoordAttackerMove,
      CoordMove,
      CoordAttackerState,
      CoordDefenderState,
      MutableWrapper[CoordAttackerMove, CoordMove, CoordAttackerState, CoordDefenderState, CoordImmutableGame]
    ](factory,
      config.roundLimit)

    GameVariantRunnerResult(result, time)
  }


  override def runWithCompactGameFactory[R](action: NormalizableFactoryAction[R]) : GameVariantRunnerResult[R] = {
    val (factory, time) = TimedExecution(new CoverageNormalizableFactory(config))
    val result = action.runWithNormalizableFactory[
      AttackerDecision, CoverageDefenderMove,
      MovingTargetsAttackerState, CoverageDefenderStateCached,
      MutableWrapper[AttackerDecision, CoverageDefenderMove, MovingTargetsAttackerState, CoverageDefenderStateCached, CoverageImmutableGame]
    ](factory, config.roundLimit)

    GameVariantRunnerResult(result, time)
  }
}
