// package server_stat -- глобальная статистика сервера
package server_stat

import (
	"encoding/json"
	"strings"
	"sync"
	"time"
	"wartank/pkg/components/kernel/logger"
	"wartank/pkg/types"
)

// СерверСтат -- структура статистики сервера
type СерверСтат struct {
	серв         types.ИСервер
	CчётСтарт_   int           `json:"count_start"`  // Количество запусков
	ВремяВсего_  time.Duration `json:"time_total"`   // Общее время работы в секундах
	ВремяСессия_ time.Duration `json:"time_session"` // Время сессии в секундах
	блок         sync.RWMutex
	лог          types.ИЛоггер
}

// НовСерверСтат -- возвращает структуру статистики сервера
func НовСерверСтат(серв types.ИСервер) *СерверСтат {
	лог := logger.НовЛоггер("СерверСтат")
	лог.Инфо("НовСерверСтат()\n")
	лог.Паника(серв == nil, "НовСерверСтат: ИСервер == nil")
	сам := &СерверСтат{
		серв:         серв,
		CчётСтарт_:   0,
		ВремяВсего_:  0,
		ВремяСессия_: 0,
		лог:          лог,
	}
	сам.загр()
	сам.CчётСтарт_++
	сам.сохр()
	go сам.пуск()
	return сам
}

// Загружает статистику сервера
func (сам *СерверСтат) загр() {
	бинДанные, ош := сам.серв.Хранилище().Получ("server_stat")
	if ош != nil {
		if strings.Contains(ош.Error(), "not found") {
			return
		}
		сам.лог.Паника(true, "СерверСтат.загр(): при загрузке статистики из хранилища, ош=\n\t%v\n", ош)
	}
	ош = json.Unmarshal(бинДанные, сам)
	сам.лог.Паника(ош != nil, "СерверСтат.загр(): при декодировании статистики из JSON, ош=\n\t%v\n", ош)
	go сам.пуск()
}

// Работает в отдельном потоке, считает время работы и счетчик запусков
func (сам *СерверСтат) пуск() {
	фнПуск := func() {
		сам.блок.Lock()
		defer сам.блок.Unlock()
		сам.ВремяВсего_ += time.Second
		сам.ВремяСессия_ += time.Second
		сам.сохр()
		time.Sleep(time.Second)
	}
	for {
		select {
		case <-сам.серв.Done():
			return
		default:
			фнПуск()
		}
	}
}

// Сохраняет статистику сервера
func (сам *СерверСтат) сохр() {
	бинДанные, ош := json.Marshal(сам)
	сам.лог.Паника(ош != nil, "СерверСтат.сохр(): при кодировании статистики в JSON, ош=\n\t%v\n", ош)
	ош = сам.серв.Хранилище().Уст("server_stat", бинДанные)
	сам.лог.Паника(ош != nil, "СерверСтат.сохр(): при сохранении статистики в хранилище, ош=\n\t%v\n", ош)
}

// СчётСтарт -- счётчик запусков
func (сам *СерверСтат) СчётСтарт() int {
	return сам.CчётСтарт_
}

// ВремяСессия -- возвращает время сессии
func (сам *СерверСтат) ВремяСессия() string {
	return сам.ВремяСессия_.String()
}

// ВремяВсего -- возвращает общее время работы
func (сам *СерверСтат) ВремяВсего() string {
	сам.блок.RLock()
	defer сам.блок.RUnlock()
	return сам.ВремяВсего_.String()
}
