package pl.edu.pw.mini.sg.util

import scala.annotation.tailrec



object StreamUtils {
  final def myStreamLength[T](stream: => Stream[T]) : Int = {
    var head = stream
    var len = 0
    while(head.nonEmpty) {
      len = len+1
      head = head.tail
    }
    len
  }

  final def streamZip[T,R](r: Stream[T], l: Stream[R]) : Stream[(T,R)] = {
    (r,l) match {
      case (headr #:: tailr, headl #:: taill) => (headr, headl)#::streamZip(tailr, taill)
      case _ => Stream.empty
    }
  }

  final def streamGrouped[T](stream: Stream[T], groupSize: Int) : Stream[Vector[T]] = {
    val batch = stream.take(groupSize).toVector
    val tail = stream.drop(groupSize)

    batch#::(if(tail.isEmpty) Stream.empty else streamGrouped(tail, groupSize))
  }

  final def streamDistinct[T](stream: => Stream[T]) : Set[T] = {
    import scala.collection.mutable.HashSet
    val mset = HashSet.empty[T]
    stream.foreach(mset.add)
    mset.toSet
  }

  final def streamMaxBy[T,U](stream: => Stream[T], fun: T => U)(implicit ord: Ordering[U]) : T = {
    var max : T = stream.head
    var first = true
    implicit val oo : Ordering[T] = Ordering.by(fun)
    stream.foreach{el =>
      if(first) { first = false; max = el}
      else max = oo.max(max, el)
    }
    require(max != null)
    max
  }
}
