package syncz

import (
	"context"
	"fmt"
)

// ValueHolder holds agent key of an agent.
type ValueHolder[T comparable] struct {
	value T
	setC  chan struct{}
}

func NewValueHolder[T comparable]() *ValueHolder[T] {
	return &ValueHolder[T]{
		setC: make(chan struct{}),
	}
}

// Set is not safe for concurrent use. It's ok since we don't need that.
func (h *ValueHolder[T]) Set(value T) error {
	select {
	case <-h.setC: // already set
		if h.value != value {
			return fmt.Errorf("value is already set to a different value: old %v, new %v", h.value, value)
		}
	default: // not set
		h.value = value
		close(h.setC)
	}
	return nil
}

func (h *ValueHolder[T]) Get(ctx context.Context) (T, error) {
	select {
	case <-h.setC:
		return h.value, nil
	case <-ctx.Done():
		var t T // nil
		return t, ctx.Err()
	}
}

func (h *ValueHolder[T]) TryGet() (T, bool) {
	select {
	case <-h.setC:
		return h.value, true
	default:
		var t T // nil
		return t, false
	}
}
