// Copyright (C) 2018 Marius Schellenberger

package jwt

import "sync"

// Blacklist is the blacklisting storage interface
type Blacklist interface {
	Add(string, int64) error
	Remove(string) error
	Check(string) bool
	Map() (BlacklistMap, error)
}

// BlacklistMap is the blacklist map structure
type BlacklistMap map[string]int64

// MemBlacklist implements the Blacklist interface
type MemBlacklist struct {
	// protects list
	sync.RWMutex
	list BlacklistMap
}

// NewMemBlacklist implements the Blacklist interface using an in-memory map
func NewMemBlacklist() *MemBlacklist {
	return &MemBlacklist{list: make(BlacklistMap)}
}

// Add adds a new token signature with expiration time to the blacklist
func (mb *MemBlacklist) Add(sig string, exp int64) error {
	mb.Lock()
	mb.list[sig] = exp
	mb.Unlock()
	return nil
}

// Remove deletes a token signature from the blacklist
func (mb *MemBlacklist) Remove(sig string) error {
	mb.Lock()
	delete(mb.list, sig)
	mb.Unlock()
	return nil
}

// Check returns true if a token signature is blacklisted and false otherwise
func (mb *MemBlacklist) Check(sig string) (ok bool) {
	mb.RLock()
	_, ok = mb.list[sig]
	mb.RUnlock()
	return
}

// Map returns the blacklist in the form of a iterable map structure for cleanup
func (mb *MemBlacklist) Map() (list BlacklistMap, err error) {
	list = make(BlacklistMap)
	mb.RLock()
	for k, v := range mb.list {
		list[k] = v
	}
	mb.RUnlock()
	return
}
