package scales.utils.collection
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue
 
sealed trait Once[T] {
  val value : T
}
trait ConcurrentMapUtils {
  def getList[K, T](key: K, mapToList: ConcurrentHashMap[K, ConcurrentLinkedQueue[T]]): ConcurrentLinkedQueue[T] = 
    valueOf(key, mapToList)(
      new ConcurrentLinkedQueue[T]())
  def removeList[K, T](key: K, mapToList: ConcurrentHashMap[K, ConcurrentLinkedQueue[T]]): ConcurrentLinkedQueue[T] = 
    removeOr(key,mapToList)(new ConcurrentLinkedQueue[T]())
   
  def removeOr[K, T](key: K, map: ConcurrentHashMap[K, T])(newT : => T): T = {
    var res = map.remove(key)
    if (res == null) {
      res = newT
    }
    res
  }
  
  def calcOnce[K,T](key : K, map : ConcurrentHashMap[K, Once[T]])( calc : => T ) : T = 
    valueOf(key, map)(new Once[T]{
	lazy val value = calc
      }).
    
    value
  
  
  def valueOf[K,T](key : K, map : ConcurrentHashMap[K, T])( newT : => T ) : T = {
    var value = map.get(key)
    if (value == null) {
      value = newT
      val res = map.putIfAbsent(key, value)
      value = if (res == null) value else res
    }
    value
  }
}