package collection

var empty struct{}

// Set est une collection de valeurs uniques.
type Set[T comparable] map[T]struct{}

// Add ajoute les valeurs en entrée dans le set et retourne le set lui-même.
func (s Set[T]) Add(in ...T) Set[T] {
	for _, e := range in {
		s[e] = empty
	}

	return s
}

// Del supprime les valeurs données en entrées du set et retourne le set lui-même.
func (s Set[T]) Del(in ...T) Set[T] {
	for _, e := range in {
		delete(s, e)
	}

	return s
}

// Contains retourne vrai si le set contient la valeur d'entrée.
func (s Set[T]) Contains(in T) (out bool) {
	_, out = s[in]

	return
}

// ContainsOneOf retourne vrai si le set contient au moins une des valeurs d’entrée.
func (s Set[T]) ContainsOneOf(in ...T) bool {
	for _, e := range in {
		if s.Contains(e) {
			return true
		}
	}

	return false
}

// ContainsAll retourne vrai si le set contient toutes les valeurs d’entrée.
func (s Set[T]) ContainsAll(in ...T) bool {
	for _, e := range in {
		if !s.Contains(e) {
			return false
		}
	}

	return true
}

// Len retourne le nombre d’éléments du set.
func (s Set[T]) Len() int {
	return len(s)
}

// ToSlice convertit un set en slice d'éléments de même type.
func (s Set[T]) ToSlice() (out []T) {
	out = make([]T, len(s))
	i := 0
	for e := range s {
		out[i] = e
		i++
	}

	return
}

// NewSet retourne un set initialisé avec les valeurs d'entrée.
func NewSet[T comparable](in ...T) (out Set[T]) {
	out = make(Set[T])
	out.Add(in...)

	return
}
