// package safe_int -- потокобезопасный целое
package safe_int

import (
	"fmt"
	"os"
	"strconv"
	"sync"

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

// safeInt -- потокобезопасное целое
type safeInt struct {
	sync.RWMutex
	val int
}

// NewSafeInt -- возвращает новое потокобезопасное целое
func NewSafeInt() ISafeInt {
	sf := &safeInt{}
	return sf
}

// NewSafeIntFromStr -- возвращает новое потокобезоппсное целое из строки
func NewSafeIntFromStr(strVal string) Result[ISafeInt] {
	sf := NewSafeInt()
	res := sf.FromStr(strVal)
	if res.IsErr() {
		err := fmt.Errorf("NewSafeIntFromStr(): in parse str(%v), err=\n\t%w", strVal, res.Err())
		return NewErr[ISafeInt](err)
	}
	return NewOk(sf)
}

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

// Get -- возвращает хранимое целое
func (sf *safeInt) Get() int {
	sf.RLock()
	defer sf.RUnlock()
	return sf.val
}

// Set -- устанавливает целое
func (sf *safeInt) Set(val int) {
	sf.Lock()
	defer sf.Unlock()
	sf.val = val
}

// Reset -- сбрасывает целое
func (sf *safeInt) Reset() {
	sf.Lock()
	defer sf.Unlock()
	sf.val = 0
}

// FromStr -- получает число из строки
func (sf *safeInt) FromStr(strVal string) Result[int] {
	iVal, err := strconv.Atoi(strVal)
	if err != nil {
		return NewErr[int](fmt.Errorf("safeInt.FromStr(): vak(%v) bad, err=\n\t%w", strVal, err))
	}
	sf.Lock()
	defer sf.Unlock()
	sf.val = iVal
	return NewOk(sf.val)
}

// Getenv -- получает значение из окружения
func (sf *safeInt) Getenv(env string) Result[int] {
	strVal := os.Getenv(env)
	res := sf.FromStr(strVal)
	if res.IsErr() {
		err := fmt.Errorf("safeInt.Getenv(): from env %v, err=\n\t%w", env, res.Err())
		return NewErr[int](err)
	}
	return res
}
