package set

type Set[T comparable] struct {
	table map[T]struct{}
}

// NewSet creates and returns a new Set.
func NewSet[T comparable]() *Set[T] {
	return &Set[T]{
		table: make(map[T]struct{}),
	}
}

// Add inserts an element into the Set.
func (s *Set[T]) Add(value T) {
	s.table[value] = struct{}{}
}

// Remove deletes an element from the Set.
func (s *Set[T]) Remove(value T) {
	delete(s.table, value)
}

// Contains checks if an element exists in the Set.
func (s *Set[T]) Contains(value T) bool {
	_, exists := s.table[value]
	return exists
}

// Size gives the element present in Set.
func (s *Set[T]) Size() int {
	return len(s.table)
}

// Empty checks if Set is empty or not.
func (s *Set[T]) Empty() bool {
	return s.Size() <= 0
}

// Values returns all elements of the Set as a slice.
// The order of elements is not guaranteed.
func (s *Set[T]) Values() []T {
	values := make([]T, 0, len(s.table))
	for v := range s.table {
		values = append(values, v)
	}
	return values
}

// Clear removes all elements from the Set.
func (s *Set[T]) Clear() {
	s.table = make(map[T]struct{})
}
