// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package principal

import (
	"reflect"
	"sync"
	"time"
)

// BlessingsCacheEntry is an entry in the blessing cache.
type BlessingsCacheEntry struct {
	refCount  uint32       // Keep track of uses so JS knows when to clean up.
	blessings *JsBlessings // For now. Switch to security.Blessings
	dirty     bool         // True iff modified since last GC.
}

// BlessingsCache is a cache for blessings.
// This cache is synced with a corresponding cache in Javascript with the goal
// of reducing the number of times that blessings objects are sent in their
// entirety.
// BlessingsCache provides an id for a blessing after a Put() call that is
// understood by Javascript.
// After a new blessings cache is created, recently unused blessings will be
// cleaned up periodically.
type BlessingsCache struct {
	lock       sync.Mutex
	nextId     BlessingsId
	entries    map[BlessingsId]*BlessingsCacheEntry
	notifier   func([]BlessingsCacheMessage)
	inactiveGc bool
}

func NewBlessingsCache(notifier func([]BlessingsCacheMessage), gcPolicy *BlessingsCacheGCPolicy) *BlessingsCache {
	bc := &BlessingsCache{
		entries:  map[BlessingsId]*BlessingsCacheEntry{},
		notifier: notifier,
	}
	go bc.gcLoop(gcPolicy)
	return bc
}

// Put a blessing in the blessing cache and get an id for it that will
// be understood by the Javascript cache.
// If the blessings object is already in the cache, a new entry won't be created
// and the id for the blessings from a previous put will be returned.
func (bc *BlessingsCache) Put(blessings *JsBlessings) BlessingsId {
	if blessings == nil {
		return 0
	}

	bc.lock.Lock()
	defer bc.lock.Unlock()

	for id, entry := range bc.entries {
		if reflect.DeepEqual(blessings, entry.blessings) {
			entry.refCount++
			entry.dirty = true
			return id
		}
	}

	bc.nextId++
	id := bc.nextId
	bc.entries[id] = &BlessingsCacheEntry{
		refCount:  1,
		blessings: blessings,
		dirty:     true,
	}
	addMessage := BlessingsCacheAddMessage{
		CacheId:   id,
		Blessings: *blessings,
	}
	bc.notifier([]BlessingsCacheMessage{
		BlessingsCacheMessageAdd{
			Value: addMessage,
		},
	})
	return id
}

// BlessingsCacheGCPolicy specifies when GC will occur and provides a function
// to pass notifications of deletions (used to notify Javascript to delete
// the cache items).
type BlessingsCacheGCPolicy struct {
	nextTrigger func() <-chan time.Time
}

// PeriodicGcPolicy periodically performs gc at the specified interval.
func PeriodicGcPolicy(interval time.Duration) *BlessingsCacheGCPolicy {
	return &BlessingsCacheGCPolicy{
		nextTrigger: func() <-chan time.Time { return time.After(interval) },
	}
}

// Stop stops the GC loop and frees up resources.
func (bc *BlessingsCache) Stop() {
	bc.lock.Lock()
	bc.inactiveGc = true
	bc.lock.Unlock()
}

func (bc *BlessingsCache) gcLoop(policy *BlessingsCacheGCPolicy) {
	for {
		bc.lock.Lock()
		if bc.inactiveGc {
			return
		}
		bc.lock.Unlock()
		<-policy.nextTrigger()
		bc.gc(policy)
	}
}

// Perform Garbage Collection.
// All blessings that weren't referenced since the last GC will be removed from
// the cache.
func (bc *BlessingsCache) gc(policy *BlessingsCacheGCPolicy) {
	bc.lock.Lock()
	defer bc.lock.Unlock()

	var toDelete []BlessingsCacheMessage
	for id, entry := range bc.entries {
		if !entry.dirty {
			deleteEntry := BlessingsCacheDeleteMessage{
				CacheId:     id,
				DeleteAfter: entry.refCount,
			}
			toDelete = append(toDelete, BlessingsCacheMessageDelete{Value: deleteEntry})
		} else {
			entry.dirty = false
		}
	}

	for _, deleteEntry := range toDelete {
		delete(bc.entries, deleteEntry.(BlessingsCacheMessageDelete).Value.CacheId)
	}

	if len(toDelete) > 0 {
		bc.notifier(toDelete)
	}
}
