package dataext

import "sync"

type SyncSet[TData comparable] struct {
	data map[TData]bool
	lock sync.Mutex
}

// Add adds `value` to the set
// returns true  if the value was actually inserted
// returns false if the value already existed
func (s *SyncSet[TData]) Add(value TData) bool {
	s.lock.Lock()
	defer s.lock.Unlock()

	if s.data == nil {
		s.data = make(map[TData]bool)
	}

	_, existsInPreState := s.data[value]
	s.data[value] = true

	return !existsInPreState
}

func (s *SyncSet[TData]) AddAll(values []TData) {
	s.lock.Lock()
	defer s.lock.Unlock()

	if s.data == nil {
		s.data = make(map[TData]bool)
	}

	for _, value := range values {
		s.data[value] = true
	}
}

func (s *SyncSet[TData]) Contains(value TData) bool {
	s.lock.Lock()
	defer s.lock.Unlock()

	if s.data == nil {
		s.data = make(map[TData]bool)
	}

	_, ok := s.data[value]

	return ok
}

func (s *SyncSet[TData]) Get() []TData {
	s.lock.Lock()
	defer s.lock.Unlock()

	if s.data == nil {
		s.data = make(map[TData]bool)
	}

	r := make([]TData, 0, len(s.data))

	for k := range s.data {
		r = append(r, k)
	}

	return r
}