package params

import "errors"

var (
	ErrParamNotFound = errors.New("parameter not found")
)

type Registration struct {
	Name        string
	ShortHand   string
	Description string
	DefaultFunc func() string
	ParseFunc   ParseFn
}

type ParseFn func(value string) (any, error)

var ParseString ParseFn = func(value string) (any, error) { return value, nil }

type Container struct {
	params map[string]Value
}

type Value struct {
	value   *string
	parseFn ParseFn
}

func (c *Container) Register(key string, parseFn ParseFn) *string {
	if c.params == nil {
		c.params = make(map[string]Value)
	}

	item, exists := c.params[key]
	if exists {
		return item.value
	}

	var str string
	value := Value{
		parseFn: parseFn,
		value:   &str,
	}
	c.params[key] = value
	return value.value
}

func (c *Container) GetValue(key string) (any, error) {
	item, exists := c.params[key]
	if !exists {
		return nil, ErrParamNotFound
	}

	return item.parseFn(*item.value)
}

// Returns a map of all parameters. Parameters that produce errors during parsing are ignored.
func (c *Container) ToMap() (out map[string]any) {
	out = make(map[string]any)
	for key := range c.params {
		v, err := c.GetValue(key)
		if err == nil {
			out[key] = v
		}
	}

	return
}
