// package safe_string -- потокобезопасная строка
package safe_string

import (
	"fmt"
	"os"
	"sync"

	. "gitp78su.ipnodns.ru/svi/kern/v2/krn/ktypes"
)

// safeString -- потокобезопасная строка
type safeString struct {
	sync.RWMutex
	val string
}

// NewSafeString -- возвращает новую потокобезопасную строку
func NewSafeString() ISafeString {
	sf := &safeString{}
	return sf
}

// NewSafeStringGetenv -- возвращает новуб потокобезопасную строку из окружения
func NewSafeStringGetenv(env string) Result[ISafeString] {
	sf := NewSafeString()
	res := sf.Getenv(env)
	if res.IsErr() {
		err := fmt.Errorf("NewSafeStringGetenv(): in get from env(%v), err=\n\t%w", env, res.Err())
		return NewErr[ISafeString](err)
	}
	return NewOk(sf)
}

// Byte -- возвращает байтовое представление строки
func (sf *safeString) Byte() []byte {
	sf.RLock()
	defer sf.RUnlock()
	return []byte(sf.val)
}

// Get -- возвращает хранимую строку
func (sf *safeString) Get() string {
	sf.RLock()
	defer sf.RUnlock()
	return sf.val
}

// Set -- устанавливает строку
func (sf *safeString) Set(val string) {
	sf.Lock()
	defer sf.Unlock()
	sf.val = val
}

// Reset -- сбрасывает строку
func (sf *safeString) Reset() {
	sf.Lock()
	defer sf.Unlock()
	sf.val = ""
}

// Getenv -- получает значение из окружения
func (sf *safeString) Getenv(env string) Result[string] {
	strVal := os.Getenv(env)
	if strVal == "" {
		err := fmt.Errorf("safeString.Getenv(): from env(%v), val is empty", env)
		return NewErr[string](err)
	}
	sf.val = strVal
	return NewOk(strVal)
}
