package keeper

/*
	Сторож системных сигналов.
	Мониторит ОС и части сервиса на завершение работы.
	В системе он должен быть только один.
*/

import (
	"os"
	"os/signal"
	"syscall"

	"wartank/pkg/types"
)

// Keeper -- сторож системных и внутренних сигналов
type Keeper struct {
	kernel types.IKernel
	slog   types.ISlog
	chSys  chan os.Signal
}

// NewKeeper -- возвращает глобальный объект сторожа *Keeper
func NewKeeper(kernel types.IKernel) *Keeper {
	if kernel == nil {
		panic("GetKeeper(): IKernel is nil")
	}

	sf := &Keeper{
		kernel: kernel,
		slog:   kernel.Slog(),
		chSys:  make(chan os.Signal, 3),
	}
	sf.kernel.Wg().Add("keeper")
	signal.Notify(sf.chSys, os.Interrupt, syscall.SIGTERM)
	go sf.run()
	sf.slog.Debugf("NewKeeper()\n")
	return sf
}

// Слушает сигналы завершения изнутри и снаружи
func (sf *Keeper) run() {
	sf.slog.Infof("Keeper.run()\n")
	defer func() {
		sf.slog.Infof("Keeper.run(): end\n")
		sf.kernel.Wg().Done("keeper")
	}()
	select {
	case sig := <-sf.kernel.Done(): // глобальная отмена контекста
		sf.slog.Infof("Keeper.run(): intern_sig=%q\n", sig)
	case sig := <-sf.chSys: // Системный сигнал закрытия
		sf.kernel.CancelApp()
		sf.slog.Infof("Keeper.run(): sys_sig=%v\n", sig)
	}
}
