package pl.edu.pw.mini.sg.game.flipit.test

import argonaut.Parse
import better.files.File
import org.rogach.scallop.ScallopConf
import pl.edu.pw.mini.game.flipit.deterministic.{ Flip, FlipItMove, NoOp }
import pl.edu.pw.mini.game.flipit.deterministic.noinfo.NoInfoFlipItGamePlugin
import pl.edu.pw.mini.sg.game.boundedrationality.BoundedRationality
import pl.edu.pw.mini.sg.game.deterministic.{ BehavioralStrategy, PureStrategy }
import pl.edu.pw.mini.sg.game.deterministic.single.LinearizedAdvanceableGame
import pl.edu.pw.mini.sg.game.util.attacker.OptimalAttacker
import pl.edu.pw.mini.sg.mixed.tree.MixedStrategyNode


final class Options(args: Seq[String]) extends ScallopConf(args) {
  val strategy = opt[List[Int]](name="strategy", short='s', required = true)
  val games = opt[List[String]](name="games", short='g', required = true).map(_.map(x => File.apply(x)))

  verify()
}

object Test {
  def main(args: Array[String]) : Unit = {
    val options = new Options(args)

    val results = options.games().map(gpath => for {
      json <- Parse.parse(gpath.contentAsString)
      gameConfig <- NoInfoFlipItGamePlugin.configJsonDecode.decodeJson(json).toEither
      game = NoInfoFlipItGamePlugin.singleCoordFactory.create(gameConfig)
      fac = NoInfoFlipItGamePlugin.singleCoordFactory
      strategy = {
        options.strategy().foldRight(Option.empty[BehavioralStrategy[fac.DefenderMove, fac.DefenderState]]){
          case (move, None) => Some(new BehavioralStrategy[fac.DefenderMove, fac.DefenderState]{
            def nextState(move: fac.DefenderMove,reachedState: fac.DefenderState): pl.edu.pw.mini.sg.game.deterministic.BehavioralStrategy[fac.DefenderMove,fac.DefenderState] = null
            def probabilities: Seq[(fac.DefenderMove, Double)] = List((if(move == -1) NoOp else Flip(move), 1.0))
            def state: fac.DefenderState = ???
            def successorsInTree: Iterable[(fac.DefenderMove, fac.DefenderState)] = ???
          })
          case (move, Some(x)) => Some(new BehavioralStrategy[fac.DefenderMove, fac.DefenderState]{
            def nextState(move: fac.DefenderMove,reachedState: fac.DefenderState): pl.edu.pw.mini.sg.game.deterministic.BehavioralStrategy[fac.DefenderMove,fac.DefenderState] = x
            def probabilities: Seq[(fac.DefenderMove, Double)] = List((if(move == -1) NoOp else Flip(move), 1.0))
            def state: fac.DefenderState = ???
            def successorsInTree: Iterable[(fac.DefenderMove, fac.DefenderState)] = ???
          })
        }.get
      }
      (response, payoff) = OptimalAttacker.calculate[
        fac.DefenderMove, fac.AttackerMove, fac.DefenderState, fac.AttackerState,
        fac.Game
      ](game, strategy)(BoundedRationality.fullyRational)
    } yield (game, response, payoff))

    val fac = NoInfoFlipItGamePlugin.singleCoordFactory
    options.games().zip(results).foreach{
      case (game, Right((g, response, payoff))) => {
        val rr = {
          def getSequence(s: fac.AttackerState, str: PureStrategy[fac.AttackerMove, fac.AttackerState], res: Vector[FlipItMove]) : Vector[FlipItMove] = {
            if(s.possibleMoves.isEmpty) res
            else {
              val ns = s.nextState(str.move)
              getSequence(ns, str.nextState(ns), res :+ str.move)
            }
          }
          getSequence(g.attackerState, response, Vector())
        }
        println(s"$game: ${payoff.real.defender}, ${payoff.real.attacker}, $rr")
      }
      case (game, Left(error)) => println(s"$game: ERROR: $error")
    }
  }
}
