package pl.edu.pw.mini.jk.sg.uct.utils

import scala.annotation.tailrec
import scala.collection.immutable.Queue

sealed trait StepLimitQueue[+E] {
  def append[EE >: E](step: Int, element: EE): StepLimitQueue[EE]
  def foreach(action: E => Unit): Unit
}

case class EmptyStepLimitQueue(limit: Int) extends StepLimitQueue[Nothing] {
  override def append[E](step: Int, element: E) = NotemptyStepLimitQueue(limit, step, List(element), Queue())
  override def foreach(action: Nothing => Unit): Unit = Unit
}

case class NotemptyStepLimitQueue[E](
  limit: Int,
  thisStepNum: Int,
  thisStep: List[E],
  previousSteps: Queue[List[E]]
) extends StepLimitQueue[E] {

  @tailrec
  private def limitQueue[T](q: Queue[List[T]]): Queue[List[T]] = if (q.length > limit) limitQueue(q.dequeue._2) else q

  override def append[EE >: E](step: Int, element: EE) =
    if (thisStepNum == step)
      copy(thisStep = element :: thisStep)
    else
      copy(thisStep = List(element), thisStepNum = step,
        previousSteps = limitQueue(previousSteps.enqueue(thisStep)))

  override def foreach(action: E => Unit) = {
    thisStep.foreach(action)
    previousSteps.foreach(_.foreach(action))
  }
}
