// package net_stat -- сетевая статистика по обмену
package net_stat

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

/*
	Сетевая статистика для сетевого соединения
*/

// СетьСтата -- статистика сетевого соединения
type СетьСтата struct {
	botNet               types.ИБотСеть
	countByteInterval    int      // Счётчик байтов в текущем интервале
	totalByte            int      // Сколько всего байт передано
	totalMinut           int      // Сколько всего минут работала передача
	countRequestInterval int      // Число запросов
	countErr             int      // Число зафиксированных ошибок
	chTick               chan int // Сигналы времени 1 раз в 5 минут
	block                sync.Mutex
	лог                  *logger.Логгер
}

// НовСетьСтата -- возвращает новый *NetStat
func НовСетьСтата(botNet types.ИБотСеть) *СетьСтата {
	лог := logger.НовЛоггер("СетьСтата")
	лог.Инфо("НовСетьСтата()\n")
	сам := &СетьСтата{
		botNet: botNet,
		chTick: make(chan int, 2),
		лог:    лог,
	}
	go сам.run()
	go сам.makeTick()
	return сам
}

// Тикер меток времени 1 раз в 5 минут
func (сам *СетьСтата) makeTick() {
	defer close(сам.chTick)
	for {
		select {
		case <-сам.botNet.Контекст().Done():
			return
		default:
			time.Sleep(time.Second * 5 * 60)
			сам.chTick <- 1
		}
	}
}

// Главный цикл работы статистики
func (сам *СетьСтата) run() {
	fnCalc := func() {
		сам.block.Lock()
		defer сам.block.Unlock()
		сам.totalMinut += 5
		mbyte := float32(сам.totalByte) / float32(сам.totalMinut*60) * (3600 * 24 * 30.5) / (1024 * 1024)
		сам.лог.Инфо("run().fnCalc(): запросы=%0.2f/сек\tтраф0=%0.2f бит/сек\tтраф1=%0.2f МБ/мес\tошибки=%v\n",
			float32(сам.countRequestInterval)/300,
			float32(сам.countByteInterval*8)/300,
			mbyte,
			сам.countErr)
		сам.countByteInterval = 0
		сам.countRequestInterval = 0
	}
	for range сам.chTick {
		select {
		case <-сам.botNet.Контекст().Done():
			return
		case <-сам.chTick:
			fnCalc()
		}
	}
}

// IncErr -- добавляет ошибку в статистику
func (сам *СетьСтата) IncErr() {
	сам.block.Lock()
	defer сам.block.Unlock()
	сам.countErr++
}

// AddByte -- увеличивает счётчик запросов и байтов на передачу/приём
func (сам *СетьСтата) AddByte(val int) {
	сам.block.Lock()
	defer сам.block.Unlock()
	сам.countByteInterval += val
	сам.totalByte += val
	сам.countRequestInterval++
}
