/*
 * Copyright (c) 2012 The Goon Authors
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package goon

import (
	"container/list"
	"reflect"
	"sync"
)

var cachedValueOverhead int

func init() {
	// Calculate the platform dependant overhead size for keeping a value in cache
	var elem list.Element
	var ci cacheItem
	cachedValueOverhead += int(reflect.TypeOf(elem).Size())   // list.Element in cache.accessed
	cachedValueOverhead += int(reflect.TypeOf(&elem).Size())  // *list.Element in cache.elements
	cachedValueOverhead += int(reflect.TypeOf(ci.key).Size()) // string in cache.elements as key
	cachedValueOverhead += int(reflect.TypeOf(ci).Size())     // cacheItem pointed to by list.Element.Value
	// In addition to the above overhead, the total cache value size must include
	// the length of the key string in bytes and the cap of the value []byte
}

type cacheItem struct {
	key   string
	value []byte
}

type cache struct {
	lock     sync.Mutex
	elements map[string]*list.Element // access via key
	accessed list.List                // most recently accessed in front
	size     int                      // Total size of all the values in the cache
	limit    int                      // Maximum size allowed
}

const defaultCacheLimit = 16 << 20 // 16 MiB

func newCache(limit int) *cache {
	return &cache{elements: map[string]*list.Element{}, limit: limit}
}

func (c *cache) setLimit(limit int) {
	c.lock.Lock()
	c.limit = limit
	c.meetLimitUnderLock()
	c.lock.Unlock()
}

// meetLimit must be called under cache.lock
func (c *cache) meetLimitUnderLock() {
	for c.size > c.limit {
		e := c.accessed.Back()
		if e == nil {
			break
		}
		c.deleteExistingUnderLock(e)
	}
}

// setUnderLock must be called under cache.lock
func (c *cache) setUnderLock(item *cacheItem) {
	// Check if there's already an entry for this key
	if e, ok := c.elements[item.key]; ok {
		// There already exists a value for this key, so update it
		ci := e.Value.(*cacheItem)
		c.size += cap(item.value) - cap(ci.value)
		// Make sure that item.key is the same pointer as the map key,
		// as this will ensure faster map lookup via pointer equality.
		// Not doing so would also lead to double memory usage, as the two key
		// pointers would be pointing to the same contents in different places.
		item.key = ci.key
		e.Value = item
		c.accessed.MoveToFront(e)
	} else {
		// Brand new key, so add it
		c.size += cachedValueOverhead + len(item.key) + cap(item.value)
		c.elements[item.key] = c.accessed.PushFront(item)
	}
}

// Set takes ownership of item and treats it as immutable
func (c *cache) Set(item *cacheItem) {
	c.lock.Lock()
	c.setUnderLock(item)
	c.meetLimitUnderLock()
	c.lock.Unlock()
}

// SetMulti takes ownership of the individual items and treats them as immutable
func (c *cache) SetMulti(items []*cacheItem) {
	c.lock.Lock()
	for _, item := range items {
		c.setUnderLock(item)
	}
	c.meetLimitUnderLock()
	c.lock.Unlock()
}

// deleteExistingUnderLock must be called under cache.lock
// The specified element must be non-nil and be guaranteed to exist in the cache
func (c *cache) deleteExistingUnderLock(e *list.Element) {
	ci := e.Value.(*cacheItem)
	c.size -= cachedValueOverhead + len(ci.key) + cap(ci.value)
	delete(c.elements, ci.key)
	c.accessed.Remove(e)
}

// deleteUnderLock must be called under cache.lock
func (c *cache) deleteUnderLock(key string) {
	if e, ok := c.elements[key]; ok {
		c.deleteExistingUnderLock(e)
	}
}

func (c *cache) Delete(key string) {
	c.lock.Lock()
	c.deleteUnderLock(key)
	c.lock.Unlock()
}

func (c *cache) DeleteMulti(keys []string) {
	c.lock.Lock()
	for _, key := range keys {
		c.deleteUnderLock(key)
	}
	c.lock.Unlock()
}

// getUnderLock must be called under cache.lock
func (c *cache) getUnderLock(key string) []byte {
	if e, ok := c.elements[key]; ok {
		c.accessed.MoveToFront(e)
		return (e.Value.(*cacheItem)).value
	}
	return nil
}

// The cache retains ownership of the []byte, so consider it immutable
func (c *cache) Get(key string) []byte {
	c.lock.Lock()
	result := c.getUnderLock(key)
	c.lock.Unlock()
	return result
}

// The cache retains ownership of the []byte, so consider it immutable
func (c *cache) GetMulti(keys []string) [][]byte {
	c.lock.Lock()
	result := make([][]byte, 0, len(keys))
	for _, key := range keys {
		result = append(result, c.getUnderLock(key))
	}
	c.lock.Unlock()
	return result
}

func (c *cache) Flush() {
	c.lock.Lock()
	c.size = 0
	c.elements = map[string]*list.Element{}
	c.accessed.Init()
	c.lock.Unlock()
}
