package safe_bool_react

import (
	"os"
	"testing"

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

type tester struct {
	t   *testing.T
	sbr ISafeBoolReact
	val bool
}

func TestSafeBoolReact(t *testing.T) {
	sf := &tester{
		t: t,
	}
	sf.create()
	sf.add()
	sf.set()
	sf.reset()
	sf.del()
	sf.newFromEnv()
	sf.newFromStr()
}

// Булево из строки
func (sf *tester) newFromStr() {
	sf.t.Log("newFromStr")
	sf.newFromStrBad1()
	sf.newFromStrGood1()
}

func (sf *tester) newFromStrGood1() {
	sf.t.Log("newFromStrGood1")
	res := NewSafeBoolReactFromStr("tRuE")
	if res.IsErr() {
		sf.t.Fatalf("newFromStrGood1(): err=%v", res.Err())
	}
	sb := res.Val()
	if val := sb.Get(); val != true {
		sf.t.Fatalf("newFromStrGood1(): val==false")
	}
}

// Кривое булево значение
func (sf *tester) newFromStrBad1() {
	sf.t.Log("newFromStrBad1")
	res := NewSafeBoolReactFromStr("0")
	if res.IsOk() {
		sf.t.Fatalf("newFromStrBad1(): err==nil")
	}
}

// Булево из окружения
func (sf *tester) newFromEnv() {
	sf.t.Log("newFromEnv")
	sf.newFromEnvBad1()
	sf.newFromEnvGood1()
	sf.newFromEnvGood2()
}

func (sf *tester) newFromEnvGood2() {
	sf.t.Log("newFromEnvGood2")
	os.Unsetenv("TEST_BOOL")
	os.Setenv("TEST_BOOL", "false")
	res := NewSafeBoolGetenv("TEST_BOOL")
	if res.IsErr() {
		sf.t.Fatalf("newFromEnvGood2(): err=%v", res.Err())
	}
	sb := res.Val()
	if val := sb.Get(); val != false {
		sf.t.Fatalf("newFromEnvGood2(): val==true")
	}
}

func (sf *tester) newFromEnvGood1() {
	sf.t.Log("newFromEnvGood1")
	os.Unsetenv("TEST_BOOL")
	os.Setenv("TEST_BOOL", "true")
	res := NewSafeBoolGetenv("TEST_BOOL")
	if res.IsErr() {
		sf.t.Fatalf("newFromEnvGood1(): err=%v", res.Err())
	}
	sb := res.Val()
	if val := sb.Get(); val != true {
		sf.t.Fatalf("newFromEnvGood1(): val==false")
	}
}

// Кривое булево значение
func (sf *tester) newFromEnvBad1() {
	sf.t.Log("newFromStrBad1")
	os.Unsetenv("TEST_BOOL")
	os.Setenv("TEST_BOOL", "bad")
	res := NewSafeBoolGetenv("TEST_BOOL")
	if res.IsOk() {
		sf.t.Fatalf("newFromStrBad1(): err==nil")
	}
}

// Удаляет функцию обратного вызова
func (sf *tester) del() {
	sf.t.Log("del")
	sf.sbr.Delete("test")
	sf.val = false
	sf.sbr.Set()
	if sf.val {
		sf.t.Fatalf("del(): val==true")
	}
}

// Добавляет функцию обратного вызова
func (sf *tester) add() {
	sf.t.Log("add")
	sf.sbr.Add("test", sf.fnBack)
}

// Функция обратного вызова для контроля
func (sf *tester) fnBack(val bool) {
	sf.val = val
}

// Сбрасывает хранимое значение
func (sf *tester) reset() {
	sf.t.Log("reset")
	sf.sbr.Reset()
	if sf.sbr.Get() {
		sf.t.Fatalf("reset(): SafeBool==true")
	}
	sf.val = true
	sf.sbr.Reset()
	if sf.sbr.Get() {
		sf.t.Fatalf("reset(): SafeBool==true")
	}
	if sf.val {
		sf.t.Fatalf("reset(): val==true")
	}
}

// Установка хранимого значения
func (sf *tester) set() {
	sf.t.Log("set")
	sf.sbr.Set()
	if !sf.sbr.Get() {
		sf.t.Fatalf("set(): SafeBool==true")
	}
	sf.sbr.Set()
	if !sf.sbr.Get() {
		sf.t.Fatalf("set(): SafeBool==true")
	}
	if !sf.val {
		sf.t.Fatalf("set(): val==false")
	}
}

// Создаёт потокобезопасный булевый признак
func (sf *tester) create() {
	sf.t.Log("create")
	sf.sbr = NewSafeBoolReact()
	if sf.sbr == nil {
		sf.t.Fatalf("create(): SafeBool==nil")
	}
	if sf.sbr.Get() {
		sf.t.Fatalf("create(): SafeBool==true")
	}
}
