package pl.edu.pw.mini.sg.gamegen

import argonaut.CodecJson
import org.apache.commons.math3.random.RandomGenerator

final case class MinMaxParameter(
  min: Double,
  max: Double
) {
  require(min <= max)
  def range = max-min
  def random(implicit rng: RandomGenerator) = rng.nextDouble()*range+min
}

object MinMaxParameter {
  implicit val codecJson : CodecJson[MinMaxParameter] = CodecJson.casecodec2(
    MinMaxParameter.apply, MinMaxParameter.unapply
  )("min", "max")
}

final case class BuildingLikeGraphGeneratorDiversePenaltyConfig(
  dimensions: BuildingDimensions,
  elevatorCount: Int,
  targetCount: Int,
  doorDensity: Double,
  interiorDensity: Double,
  attackerCaughtPenaltyTarget: MinMaxParameter,
  attackerCaughtPenaltyNormal: MinMaxParameter,
  defenderSuccessRewardTarget: Double,
  defenderSuccessRewardNormal: Double,
  defenderPenalty: MinMaxParameter,
  attackerReward: MinMaxParameter,
  numberOfDefenders: Int,
  rounds: Int
) {
  /** The returned config is usable only for a graph structure. Payoff values 
    * are set to meaningless values. 
    */
  private[gamegen] def toBLGGC : BuildingLikeGameGeneratorConfig = new BuildingLikeGameGeneratorConfig(
    dimensions, elevatorCount, targetCount, doorDensity, interiorDensity, -1, -1, -1, -1, 10, 10, 1, numberOfDefenders, false
  )
}


object BuildingLikeGraphGeneratorDiversePenaltyConfig {
  implicit val buildingDimensionsCodec : CodecJson[BuildingDimensions] =
    CodecJson.codec3[Int, Int, Int, BuildingDimensions](
      (w, h, fc) => new BuildingDimensions(w, h, fc),
      bd => (bd.getWidth, bd.getHeight, bd.getFloorCount)
    )(
      "width", "height", "floorCount"
    )

  implicit val codecJson: CodecJson[BuildingLikeGraphGeneratorDiversePenaltyConfig] =
    CodecJson.casecodec13(
      BuildingLikeGraphGeneratorDiversePenaltyConfig.apply, BuildingLikeGraphGeneratorDiversePenaltyConfig.unapply
    )(
      "buildingDimensions", "elevatorCount", "targetCount", "doorDensity",
      "interiorDensity", "attackerCaughtPenaltyTarget",
      "attackerCaughtPenaltyNormal", "defenderSuccessRewardTarget",
      "defenderSuccessRewardNormal", "defenderPenalty", "attackerReward",
      "numberOfDefenders", "rounds"
    )
}
