package pl.edu.pw.mini.game.flipit.deterministic.allpoints

import pl.edu.pw.mini.game.flipit.deterministic.{ Flip, FlipItMove, NoOp }
import pl.edu.pw.mini.sg.game.deterministic.PlayerVisibleState


sealed trait AllPointsFlipItDefenderState extends
    PlayerVisibleState[FlipItMove] {
  def next(move: FlipItMove, succcess: Boolean, payoff: Double) : AllPointsFlipItDefenderState
}

object AllPointsFlipItDefenderStateTerminal extends AllPointsFlipItDefenderState {
  override def possibleMoves: List[FlipItMove] = Nil

  override def next(move: FlipItMove, succcess: Boolean, payoff: Double) : AllPointsFlipItDefenderState =
    throw new IllegalStateException("terminal state")
}

final class AllPointsFlipItDefenderStateInner(
  val possiblyOwnedVertices: Set[Int],
  val round: Int,
  val payoff: Double,
  val previousMoveSuccess: Boolean,
  cache: Cache
) extends AllPointsFlipItDefenderState {
  override def equals(other: Any) : Boolean = other match {
    case s : AllPointsFlipItDefenderStateInner => s.round == round && s.possiblyOwnedVertices == possiblyOwnedVertices && s.payoff == payoff && s.previousMoveSuccess == previousMoveSuccess
    case _ => false
  }
  override lazy val hashCode = (possiblyOwnedVertices, previousMoveSuccess, round, payoff).##
  override def possibleMoves : List[FlipItMove] = cache.allMoves

  def next(move: FlipItMove, success: Boolean, payoff: Double) : AllPointsFlipItDefenderState = {
    if(round == cache.config.rounds)
      AllPointsFlipItDefenderStateTerminal
    else 
      new AllPointsFlipItDefenderStateInner(move match {
        case NoOp => possiblyOwnedVertices
        case x: Flip if success => possiblyOwnedVertices+x.vertex
        case x: Flip if !success => possiblyOwnedVertices-x.vertex
      }, 
        round+1, payoff, success, cache)
  }
}
