package ds

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

var _ Coll[int] = &Set[int]{}

func NewSet[T comparable]() *Set[T] {
	return &Set[T]{}
}

func (s *Set[T]) init() {
	if s.values == nil {
		s.values = map[T]struct{}{}
	}
}

func (s *Set[T]) Add(value T) {
	s.init()
	s.values[value] = struct{}{}
}

func (s *Set[T]) AddAll(values Iterable[T]) {
	s.init()
	values.Each(s.Add)
}

func (s *Set[T]) Remove(value T) {
	s.init()
	delete(s.values, value)
}

func (s *Set[T]) RemoveAll(values Iterable[T]) {
	values.Each(s.Remove)
}

func (s *Set[T]) Clear() {
	s.values = map[T]struct{}{}
}

func (s *Set[T]) Has(value T) bool {
	s.init()
	_, ok := s.values[value]
	return ok
}

func (s *Set[T]) Size() int {
	s.init()
	return len(s.values)
}

func (s *Set[T]) Empty() bool {
	return s.Size() == 0
}

func (s *Set[T]) Each(f func(value T)) {
	for value := range s.values {
		f(value)
	}
}