package label

import (
	"k8s.io/apimachinery/pkg/labels"
)

// TODO: use a more reasonable package
type Object[T any] interface {
	Desc(desc string) Object[T]
	Labels(ls Labels) Object[T]

	Get() T
	GetDesc() string
	GetLabels() Labels
	GetState() State

	Fail(err error)
	Skip()
	Succeed()

	Error() error

	DeepCopy() Object[T]
}

type Labels interface {
	labels.Labels

	Length() int
	Range(func(k, v string) bool)
}

type Label interface {
	Key() string
	Value() string
}

type kv struct {
	k string
	v string
}

func NewLabel(k, v string) Label {
	return &kv{
		k: k,
		v: v,
	}
}

func (l *kv) Key() string {
	return l.k
}

func (l *kv) Value() string {
	return l.v
}

type LabelSet labels.Set

func (s LabelSet) Has(key string) bool {
	_, ok := s[key]
	return ok
}

func (s LabelSet) Get(key string) string {
	return s[key]
}

func (s LabelSet) Length() int {
	return len(s)
}

func (s LabelSet) Range(f func(k, v string) bool) {
	for k, v := range s {
		if stop := f(k, v); stop {
			break
		}
	}
}

func (s LabelSet) Merge(ls Labels) {
	ls.Range(func(k, v string) bool {
		s[k] = v
		return false
	})
}

func HasConflicts(a, b Labels) (string, bool) {
	small := a
	big := b
	if b.Length() < a.Length() {
		small = b
		big = a
	}

	hasConflict := false
	conflictKey := ""

	small.Range(func(k, v string) bool {
		if big.Has(k) {
			val := big.Get(k)
			if val != v {
				conflictKey = k
				hasConflict = true
				return true
			}
		}
		return false
	})

	return conflictKey, hasConflict
}
