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

import java.io.{File => JFile}
import java.util.UUID

import argonaut.{JsonIdentity, Parse}
import better.files.File
import org.apache.commons.math3.random.{MersenneTwister, RandomGenerator}
import org.rogach.scallop.ScallopConf
import pl.edu.pw.mini.game.flipit.deterministic.FlipItConfig


final class Options(args: Seq[String]) extends ScallopConf(args) {
  val config = opt[JFile](name = "config", short = 'c', required = true).map(f => 
    better.files.FileOps(f).toScala)
  val outputs = opt[List[String]](name = "output-prefixes", short = 'o', required = true)
    .map(_.map((f:String) => File(f)))

  verify()
}

object Generator {
  def main(args: Array[String]) : Unit = {
    val options = new Options(args)
    implicit val rng : RandomGenerator = new MersenneTwister()
    Parse.parse(options.config().contentAsString)
      .flatMap(j => j.as[GeneratorConfig].toEither.left.map(_.toString))
      .map(c => options.outputs().map(randomGame(c, _)))
      match {
        case Right(_) => {}
        case Left(error) => println(s"Error:\n${error}"); sys.exit(1)
      }
  }

  def randomGame(config: GeneratorConfig, output: File)(implicit rng: RandomGenerator) : Unit = {
    import JsonIdentity._
    val outputAP = File(output.pathAsString+".apflip")
    val outputNI = File(output.pathAsString+".niflip")
    val rg = randomGame(config)
    outputAP.overwrite(rg.asJson.spaces2)
    outputNI.overwrite(rg.copy(id = UUID.randomUUID()).asJson.spaces2)
  }

  def randomGame(config: GeneratorConfig)(implicit rng: RandomGenerator) : FlipItConfig = {
    val rewards = Vector.fill(config.graph.vertexCount)(config.rewardConfig.getRewardsForVertex)
    FlipItConfig(
      id = UUID.randomUUID(),
      graph = config.graph,
      rounds = config.rounds,
      defenderRewards = rewards.map(_.defenderReward),
      attackerRewards = rewards.map(_.attackerReward),
      defenderCosts = rewards.map(_.defenderCost),
      attackerCosts = rewards.map(_.attackerCost),
      entryNodes = config.entryPoints.toSet
    )
  }
}
