package parse_hour

import (
	"fmt"
	"strconv"
	"sync"
	"wartank/pkg/alias"
	"wartank/pkg/types"
)

/*
	Потокобезопасно парсит из строки значение часа
*/

// ПарсерЧас -- потокобезопасный парсер часа из строки
type ПарсерЧас struct {
	знач alias.Час // Значение часа
	блок sync.RWMutex
}

// НовПарсерЧас -- возвращает новый *ПарсерЧас
func НовПарсерЧас() *ПарсерЧас {
	сам := &ПарсерЧас{}
	_ = types.ИПарсерЧас(сам)
	return сам
}

// ПолучМилСек -- возвращает общее число милСек
func (сам *ПарсерЧас) ПолучМилСек() alias.МилСек {
	return alias.МилСек(сам.знач * 3_600 * 1_000)
}

// Получ -- возвращает хранимое значение
func (сам *ПарсерЧас) Получ() alias.Час {
	сам.блок.RLock()
	defer сам.блок.RUnlock()
	return сам.знач
}

// String -- возвращает строковое значение часов
func (сам *ПарсерЧас) String() string {
	сам.блок.RLock()
	defer сам.блок.RUnlock()
	res := fmt.Sprintf("%02d", сам.знач)
	return res
}

// Сброс -- сбрасывает значение часов
func (сам *ПарсерЧас) Сброс() {
	сам.блок.Lock()
	defer сам.блок.Unlock()
	сам.знач = 0
}

// Уст -- устанавливает значение часов
//
//	Значение часов может быть больше 24
func (сам *ПарсерЧас) Уст(часы alias.Время) error {
	сам.блок.Lock()
	defer сам.блок.Unlock()
	цЧасы, err := strconv.Atoi(string(часы))
	if err != nil {
		return fmt.Errorf("ПарсерЧас.Уст(): часы(%q) не число, err=\n\t%w", часы, err)
	}
	if цЧасы < 0 {
		return fmt.Errorf("ПарсерЧас.Уст(): часы(%q) меньше нуля, err=\n\t%w", часы, err)
	}
	if err := сам.уст(alias.Час(цЧасы)); err != nil {
		return fmt.Errorf("ПарсерЧас.Уст(): in internal set hour(%q), err=\n\t%w", часы, err)
	}
	return nil
}

// УстЧас -- устанавливает числовое значение часов
func (сам *ПарсерЧас) УстЧас(часы alias.Час) error {
	сам.блок.Lock()
	defer сам.блок.Unlock()
	if err := сам.уст(часы); err != nil {
		return fmt.Errorf("ПарсерЧас.УстЧас(): in internal set hour(%v), err=\n\t%w", часы, err)
	}
	return nil
}

// Внутренняя процедура для числовой установки часов без блокировки
func (сам *ПарсерЧас) уст(часы alias.Час) error {
	сам.знач = часы
	return nil
}
