package dataext

import (
	"encoding/json"
	"errors"
)

type JsonOpt[T any] struct {
	isSet bool
	value T
}

// MarshalJSON returns m as the JSON encoding of m.
func (m JsonOpt[T]) MarshalJSON() ([]byte, error) {
	if !m.isSet {
		return []byte("null"), nil // actually this would be undefined - but undefined is not valid JSON
	}

	return json.Marshal(m.value)
}

// UnmarshalJSON sets *m to a copy of data.
func (m *JsonOpt[T]) UnmarshalJSON(data []byte) error {
	if m == nil {
		return errors.New("JsonOpt: UnmarshalJSON on nil pointer")
	}

	m.isSet = true
	return json.Unmarshal(data, &m.value)
}

func (m JsonOpt[T]) IsSet() bool {
	return m.isSet
}

func (m JsonOpt[T]) IsUnset() bool {
	return !m.isSet
}

func (m JsonOpt[T]) Value() (T, bool) {
	if !m.isSet {
		return *new(T), false
	}
	return m.value, true
}

func (m JsonOpt[T]) ValueOrNil() *T {
	if !m.isSet {
		return nil
	}
	return &m.value
}

func (m JsonOpt[T]) MustValue() T {
	if !m.isSet {
		panic("value not set")
	}
	return m.value
}