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

import pl.edu.pw.mini.sg.game.deterministic.{ DeterministicGame, PlayerVisibleState }



final class LazyGameState[DM, AM,
  DS <: PlayerVisibleState[DM],
  AS <: PlayerVisibleState[AM],
  G <: DeterministicGame[DM, AM, DS, AS, G]] private (
) {
  private var parent: (LazyGameState[DM, AM, DS, AS, G], DM, AM) = null
  private var evaluatedState: G = _

  def state : G = {
    parent match {
      case (ls, dm, am) => {
        val ps = ls.state
        evaluatedState = ps.makeMove(dm, am)
        parent = null
        evaluatedState
      }
      case _ => {
        require(evaluatedState != null)
        evaluatedState
      }
    }
  }

  def makeMove(dm :DM, am: AM) : LazyGameState[DM, AM, DS, AS, G] = {
    val r = new LazyGameState[DM, AM, DS, AS, G]()
    r.parent = (this, dm, am)
    r
  }
}

object LazyGameState {
  def apply[DM, AM,
    DS <: PlayerVisibleState[DM],
    AS <: PlayerVisibleState[AM],
    G <: DeterministicGame[DM, AM, DS, AS, G]](state: G) : LazyGameState[DM, AM, DS, AS, G] = {
    val ret = new LazyGameState[DM, AM, DS, AS, G]()
    ret.evaluatedState = state
    ret
  }
}
