package pl.edu.pw.mini.sg.checker

import better.files.{ File, Scannable, Scanner, StringSplitter }
import pl.edu.pw.mini.sg.game.deterministic.BehavioralStrategy
import pl.edu.pw.mini.sg.game.graph.sud.SingleUnitDefenderState
import scala.annotation.tailrec



final case class MixedStrategy(
  entries: List[(Double, Vector[Int])]
) {
  def toBehavioralStrategy(startState: SingleUnitDefenderState) : BehavioralStrategy[Int, SingleUnitDefenderState] = 
    generateNode(entries, startState)

  private final def generateNode(node : List[(Double, Vector[Int])], currentState: SingleUnitDefenderState) :
      BehavioralStrategy[Int, SingleUnitDefenderState] = {
    val g = node.groupBy(_._2.head).toList
    val probsum = node.map(_._1).sum
    val probs = g.map{case (m, list) => (m, list.map(_._1).sum/probsum)}
    val tails = g.map{case (m, list) => (m, list.map(x => (x._1, x._2.tail)).filter(_._2.nonEmpty))}
    val succS = g.map{case (m, _) => (m, currentState.continuation(m))}

    new BehavioralStrategy[Int, SingleUnitDefenderState]() {
      def nextState(move: Int,reachedState: SingleUnitDefenderState): BehavioralStrategy[Int,SingleUnitDefenderState] =
        if(tails.find(_._1 == move).get._2.isEmpty)
          new BehavioralStrategy[Int, SingleUnitDefenderState]() {
            def nextState(move: Int,reachedState: SingleUnitDefenderState): BehavioralStrategy[Int,SingleUnitDefenderState] = ???
            def probabilities = Nil
            def state = currentState.continuation(move)
            def successorsInTree = Nil
          }
        else
          generateNode(tails.find(_._1 == move).get._2, currentState.continuation(move))
      def probabilities: Seq[(Int, Double)] = probs
      def state: SingleUnitDefenderState = currentState
      def successorsInTree: Iterable[(Int, SingleUnitDefenderState)] = succS
    }
  }
}

object MixedStrategy {
  @tailrec private final def toVector[T](scanner: Scanner, vec: Vector[T])(implicit s: Scannable[T]) : Vector[T] =
    if(scanner.hasNext) toVector(scanner, vec:+scanner.next[T])
    else vec

  def readFromFile(file: File) : MixedStrategy = {
    MixedStrategy(file.lines.map(line => {
      println(line)
      val scanner = Scanner(line, StringSplitter.anyOf(" ,:", false))
      val prob = scanner.next[Double]
      val vec = toVector[Int](scanner, Vector())
      (prob, vec)
    }).toList)
  }
}
