package pl.edu.pw.mini.sg.mixed.expander

import argonaut.{CodecJson, DecodeJson, DecodeResult, EncodeJson, Json}
import pl.edu.pw.mini.sg.game.deterministic.TreeExpander
import pl.edu.pw.mini.sg.game.deterministic.single.GameWithPayoff
import pl.edu.pw.mini.sg.json.{ FlatTraitJsonCodec, TraitSubtypeCodec }
import pl.edu.pw.mini.sg.mcts.MctsParameters

object ExpanderJson {
  implicit val gwpEvaluationEncode : EncodeJson[GWPEvaluation] =
    EncodeJson((ge: GWPEvaluation) => Json.jString(ge match {
      case PositiveAttacker => "positiveAttacker"
      case NegativeAttacker => "negativeAttacker"
      case PositiveDefender => "positiveDefender"
      case NegativeDefender => "negativeDefender"
    }))

  implicit val gwpEvaluationDecode : DecodeJson[GWPEvaluation] =
    DecodeJson( hc => 
      DecodeJson.StringDecodeJson(hc).flatMap(_ match {
        case "positiveAttacker" => DecodeResult.ok(PositiveAttacker)
        case "negativeAttacker" => DecodeResult.ok(NegativeAttacker)
        case "positiveDefender" => DecodeResult.ok(PositiveDefender)
        case "negativeDefender" => DecodeResult.ok(NegativeDefender)
      })
    )

  def mctsExpanderCodec(implicit mctsParamsEncode: EncodeJson[MctsParameters],
    mctsParamsDecode: DecodeJson[MctsParameters]) : CodecJson[MctsExpander] =
    CodecJson.casecodec2(MctsExpander.apply, MctsExpander.unapply)("mctsParams", "evaluationFunction")


  implicit def expanderCodec(
    implicit mctsParamsEncode: EncodeJson[MctsParameters],
    mctsParamsDecode: DecodeJson[MctsParameters]
  ) : FlatTraitJsonCodec[TreeExpander[Any, Any, GameWithPayoff]] =
    new FlatTraitJsonCodec(List(
      TraitSubtypeCodec(mctsExpanderCodec, mctsExpanderCodec, "mcts")
    ))

}
