// package safe_bool -- потокобезопасный булевый признак
package safe_bool

import (
	"fmt"
	"os"
	"strings"
	"sync"

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

// safeBool -- потокобезопасный булевый признак
type safeBool struct {
	sync.RWMutex
	val bool
}

// NewSafeBool -- возвращает новый потокобезопасный булевый признак
func NewSafeBool() ISafeBool {
	sf := &safeBool{}
	return sf
}

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

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

// Get -- возвращает хранимый булевый признак
func (sf *safeBool) Get() bool {
	sf.RLock()
	defer sf.RUnlock()
	return sf.val
}

// Set -- устанавливает булевый признак
func (sf *safeBool) Set() {
	sf.Lock()
	defer sf.Unlock()
	sf.val = true
}

// Reset -- сбрасывает булевый признак
func (sf *safeBool) Reset() {
	sf.Lock()
	defer sf.Unlock()
	sf.val = false
}

// FromStr -- получает число из строки
func (sf *safeBool) FromStr(strVal string) Result[bool] {
	strVal = strings.ToLower(strVal)
	sf.Lock()
	defer sf.Unlock()
	switch strVal {
	case "true":
		sf.val = true
	case "false":
		sf.val = false
	default:
		return NewErr[bool](fmt.Errorf("safeBool.FromStr(): val(%v) bad", strVal))
	}
	return NewOk(sf.val)
}

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