-_ = require './util'
-stats = require('./stats').getChildClient('cache')
+_ = require 'underscore'
 
 class Cache
 
   constructor: (opts = {}) ->
     { @max_items } = opts
-    @lru_size = 0
-    @sticky_size = 0
     unless @max_memory || @max_items
       throw new Error "Must specify some kind of size limit"
     @reset()

    while (item = next) != @head
      next = item.next
      item.key

  gauge_size: ->
    stats.gauge 'size.lru', @lru_size
    stats.gauge 'size.sticky', @sticky_size

class CacheItem


    @map = {}
    @head = new CacheItem
    @head.next = @head.prev = @head
    @stats =
      lru_items: 0
      sticky_items: 0
      lru_hits: 0
      sticky_hits: 0
      misses: 0
      added: 0
      removed: 0

  add: (key, value, sticky = false) ->
    return item.get() if item = (@sticky[key] || @map[key])
    item = new CacheItem key, value
    if sticky
      @stats.sticky_items++
      @sticky[key] = item
      return item.get()
    @shrink()
    item.add_after @head
    @stats.lru_items++
    @stats.added++
    @map[key] = item
    item.get()

  remove: (key) ->
    if item = @map[key]
      delete @map[key]
      item.remove()
      @stats.lru_items--
      @stats.removed++
      item.value

  get: (key) ->
    if (item = @sticky[key]) != undefined
      @stats.sticky_hits++
      item.get()
    else if item = @map[key]
      item.hits++
      @stats.lru_hits++
      unless item == @head.next
        item.remove()
        item.add_after @head
      item.get()
    else
      @stats.misses++
      undefined

  shrink: ->
    while true
      break if @max_items && (@stats.lru_items < @max_items)
      @remove @head.prev.key

  keys: ->
