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

import argonaut.CodecJson
import org.apache.commons.math3.random.RandomGenerator
import pl.edu.pw.mini.sg.game.graph.{ GraphConfig, GraphConfigJson }

final case class Payoffs(
  defenderReward: Double,
  defenderCost: Double,
  attackerReward: Double,
  attackerCost: Double
)

final case class RewardLimits(
  minReward: Double,
  maxReward: Double,
  minCost: Double,
  maxCost: Double
)

final case class RewardConfig(
  types: Vector[RewardLimits]
) {
  def getRewardsForVertex(implicit rng: RandomGenerator) : Payoffs = {
    val t = types(rng.nextInt(types.size))
    val reward = t.minReward+ rng.nextDouble()*(t.maxReward - t.minReward)
    val cost = t.minCost + rng.nextDouble()*(t.maxCost - t.minCost)

    Payoffs(reward, cost, reward, cost)
  }
}

final case class GeneratorConfig(
  graph: GraphConfig,
  entryPoints: Vector[Int],
  rewardConfig: RewardConfig,
  rounds: Int
)

object GeneratorConfig {
  implicit val rewardLimitsCodec: CodecJson[RewardLimits] =
    CodecJson.casecodec4(RewardLimits.apply, RewardLimits.unapply)(
      "minReward", "maxReward", "minCost", "maxCost"
    )

  implicit val rewardConfigCodec: CodecJson[RewardConfig] =
    CodecJson.casecodec1(RewardConfig.apply, RewardConfig.unapply)("types")

  import GraphConfigJson.graphConfigCodec
  implicit val generatorConfigCodec: CodecJson[GeneratorConfig] = CodecJson.casecodec4(
    GeneratorConfig.apply, GeneratorConfig.unapply
  )("graph", "entryPoints", "rewardConfig", "rounds")
}
