package sshchat

import (
	"sync"
	"time"
)

type expiringValue struct {
	time.Time
}

func (v expiringValue) Bool() bool {
	return time.Now().Before(v.Time)
}

type value struct{}

func (v value) Bool() bool {
	return true
}

type setValue interface {
	Bool() bool
}

// Set with expire-able keys
type Set struct {
	sync.Mutex
	lookup map[string]setValue
}

// NewSet creates a new set.
func NewSet() *Set {
	return &Set{
		lookup: map[string]setValue{},
	}
}

// Len returns the size of the set right now.
func (s *Set) Len() int {
	s.Lock()
	defer s.Unlock()
	return len(s.lookup)
}

// In checks if an item exists in this set.
func (s *Set) In(key string) bool {
	s.Lock()
	v, ok := s.lookup[key]
	if ok && !v.Bool() {
		ok = false
		delete(s.lookup, key)
	}
	s.Unlock()
	return ok
}

// Add item to this set, replace if it exists.
func (s *Set) Add(key string) {
	s.Lock()
	s.lookup[key] = value{}
	s.Unlock()
}

// Add item to this set, replace if it exists.
func (s *Set) AddExpiring(key string, d time.Duration) time.Time {
	until := time.Now().Add(d)
	s.Lock()
	s.lookup[key] = expiringValue{until}
	s.Unlock()
	return until
}