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

import (
	"fmt"
	"sync"

	"gitp78su.ipnodns.ru/svi/kern/v3/krn/kint"
	. "gitp78su.ipnodns.ru/svi/kern/v3/krn/ktypes"
)

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

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

// NewSafeIntFromStr -- возвращает новое потокобезопасное целое из строки
func NewSafeIntFromStr(strVal string) Result[ISafeInt] {
	sf := NewSafeInt(0)
	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(0)
	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)
}

// FromBool -- устанавливает значение из булева значения
func (sf *safeInt) FromBool(val bool) int {
	sf.Lock()
	defer sf.Unlock()
	return sf.val.FromBool(val)
}

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

// Dec -- уменьшает значение на 1
func (sf *safeInt) Dec() {
	sf.Lock()
	defer sf.Unlock()
	sf.val.Dec()
}

// Inc -- увеличивает значение на 1
func (sf *safeInt) Inc() {
	sf.Lock()
	defer sf.Unlock()
	sf.val.Inc()
}

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

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

// FromStr -- получает число из строки
func (sf *safeInt) FromStr(strVal string) Result[int] {
	sf.Lock()
	defer sf.Unlock()
	return sf.val.FromStr(strVal)
}

// FromByte -- получает число из среза байт
func (sf *safeInt) FromByte(binData []byte) Result[int] {
	sf.Lock()
	defer sf.Unlock()
	return sf.val.FromByte(binData)
}

// ToByte -- конвертирует число в срез байт
func (sf *safeInt) ToByte() []byte {
	sf.RLock()
	defer sf.RUnlock()
	return sf.val.ToByte()
}

// ToBool -- конвертирует число в bool
func (sf *safeInt) ToBool() bool {
	sf.RLock()
	defer sf.RUnlock()
	return sf.val.ToBool()
}

// ToStr -- конвертирует число в строку
func (sf *safeInt) ToStr() string {
	sf.RLock()
	defer sf.RUnlock()
	return sf.val.ToStr()
}

// Getenv -- получает значение из окружения
func (sf *safeInt) Getenv(env string) Result[int] {
	sf.Lock()
	defer sf.Unlock()
	return sf.val.Getenv(env)
}
