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

import com.google.common.cache.CacheBuilder
import com.google.common.collect.ImmutableList
import pl.edu.pw.mini.jk.sg.game.graph.advanceable.{ AdvanceableDefenderGraphState, AdvanceableGraphGameConfiguration, AdvanceableStateGraphGame, AttackerAdvaceableGraphState }
import pl.edu.pw.mini.jk.sg.game.graph.moves.many.advanceable.{ AdvanceableMultiMoveAttackerState, AdvanceableMultiMoveDefenderState, ManyMovesAdvanceableStateGame, SingleUnitDestination }
import pl.edu.pw.mini.jk.sg.game.graph.moves.single.{ DesiredConfigurationMove }
import pl.edu.pw.mini.jk.sg.game.{ GameVariantRunner, NormalizableFactoryAction, GameVariantRunnerResult }
import pl.edu.pw.mini.jk.lib.TimedExecution

case class GraphGameVariantRunner(gameConfig: AdvanceableGraphGameConfiguration, gameLength: Int) extends GameVariantRunner {
  override def runWithSingleMovePerTimestepFactory[R](action: NormalizableFactoryAction[R]) : GameVariantRunnerResult[R] = {
    val (fac, time) = TimedExecution(new NormalizableAdvanceableStateGraphGameFactory(gameConfig,
      Some(CacheBuilder.newBuilder().build[Object, ImmutableList[DesiredConfigurationMove]]()), true))
    val res = action.runWithNormalizableFactory[
      DesiredConfigurationMove, DesiredConfigurationMove,
      AttackerAdvaceableGraphState,
      AdvanceableDefenderGraphState,
      AdvanceableStateGraphGame
    ](fac, gameLength)
    GameVariantRunnerResult(res, time)
  }
  override def runWithMultiMovePerTimestepFactory[R](action: NormalizableFactoryAction[R]): GameVariantRunnerResult[R] =
  {
    val (factory, time) = TimedExecution(new NormalizableManyMovesAdvanceableStateGameFactory(gameConfig, CacheBuilder.newBuilder().build(), true))
    val result = action.runWithNormalizableFactory[
      SingleUnitDestination, SingleUnitDestination,
      AdvanceableMultiMoveAttackerState,
      AdvanceableMultiMoveDefenderState,
      ManyMovesAdvanceableStateGame
    ](factory,      gameLength)
    GameVariantRunnerResult(result, time)
  }

  // Nie ma bardziej szczegółowego wariantu
  override def runWithCoordGameFactory[R](action: NormalizableFactoryAction[R]) : GameVariantRunnerResult[R] = runWithMultiMovePerTimestepFactory(action)

  override def runWithCompactGameFactory[R](action: NormalizableFactoryAction[R]) : GameVariantRunnerResult[R] = runWithSingleMovePerTimestepFactory(action)
}
