package pl.edu.pw.mini.sg.se

import argonaut.{CursorHistory, Json}
import pl.edu.pw.mini.sg.game.boundedrationality.DistortedPayoff
import pl.edu.pw.mini.sg.game.deterministic.plugin.GameParams
import pl.edu.pw.mini.sg.game.deterministic.{AdvanceablePlayerVisibleState, DeterministicGame, PlayerVisibleState}
import pl.edu.pw.mini.sg.mixed.{NestedMcsAttackerSampler, NestedMcsAttackerSamplerConfig, NestedMcsAttackerSamplerConfigJson}
import pl.edu.pw.mini.sg.mixed.tree.MixedStrategyNode
import pl.edu.pw.mini.sg.results.{MethodInfo, NewMixedMethodInfo}
import pl.edu.pw.mini.sg.rng.RandomGenerator
import scalaz.{NonEmptyList, Validation}
import squants.Time
import squants.time.Nanoseconds


final class NestedMcsSamplerMethod(
  config: NestedMcsAttackerSamplerConfig
) extends StrategyMethod {
  def findBehavioralStrategy[
    DM, AM,
    DS <: PlayerVisibleState[DM],
    AS <: AdvanceablePlayerVisibleState[AM, AS],
    G <: DeterministicGame[DM, AM, DS, AS, G]
  ](
    game: G, params: GameParams, rng: RandomGenerator
  ) : (MixedStrategyNode[DM, DS, Unit], DistortedPayoff, Time) = {
    val (strategy, payoff) = NestedMcsAttackerSampler.findBehavioralStrategy[DM, AM, DS, AS, G](game, params, config)(rng)
    (strategy, payoff, Nanoseconds(0))
  }

  override def getMethodInfo(configFileName: String, gitHash: String, version: String): MethodInfo = {
    NewMixedMethodInfo(configFileName, gitHash, version)
  }
}

object NestedMcsAttackerSamplerMethod extends StrategyMethodParser[NestedMcsSamplerMethod] {
  def tryParse(config: Json) : Validation[NonEmptyList[(String, CursorHistory)], NestedMcsSamplerMethod] =
    Validation
      .fromEither(config.as(NestedMcsAttackerSamplerConfigJson.nestedMcsAttackerSamplerConfigCodec).toEither)
      .map(new NestedMcsSamplerMethod(_)).toValidationNel

  override val name = "NMCS"
}

