// Package kernel -- объект ядра приложения
//
//	Содержит базовый функционал сервиса
package kernel

import (
	"context"
	"sync"
	"wartank/pkg/components/kernel/keeper"
	"wartank/pkg/components/kernel/logger"
	"wartank/pkg/components/kernel/store"
	"wartank/pkg/components/kernel/wgname"
	"wartank/pkg/types"
)

/*
	Базовый объект приложения.
*/

// Ядро -- объект ядра приложения
type Ядро struct {
	ctxBg    context.Context  // Неотменяемый контекст приложения
	ctxApp   context.Context  // Отменяемый контекст приложения
	fnCancel func()           // Функция отмены приложения
	keeper   *keeper.Сторож   // Сторож системных сигналов
	лог      types.ИЛоггер    // Логгер в два вывода
	wg       *wgname.WgName   // Групповое ожидание частей приложения
	хран     types.ИХранилище // Хранилище данных
	блок     sync.Mutex
}

// НовЯдро -- возвращает новый *Ядро
func НовЯдро() types.ИЯдро {
	лог := logger.НовЛоггер("Ядро")
	лог.Инфо("НовЯдро()\n")
	// timeStart := time.Now().UTC().Format("2006-10-02 15:04:05.000")
	// fmt._rintf("%v\t%v\tCI/CD test\n", cons.SelfName, timeStart)
	сам := &Ядро{
		ctxBg: context.Background(),
		wg:    wgname.NewWgName(),
		лог:   лог,
	}
	var ош error
	сам.ctxApp, сам.fnCancel = context.WithCancel(сам.ctxBg)
	сам.хран, ош = store.НовХранилище(сам, "./store")
	сам.лог.Паника(сам.хран == nil, "НовЯдро(): при создании ИХранилище, ош=\n\t%v\n", ош)
	сам.блок.Lock()
	сам.лог = logger.НовЛоггер("Ядро")
	сам.блок.Unlock()
	сам.лог.Отладка("НовЯдро()")
	сам.keeper = keeper.НовСторож(сам)
	return сам
}

// Хранилище -- возвращает хранилище данных
func (сам *Ядро) Хранилище() types.ИХранилище {
	return сам.хран
}

// Wg -- возвращает объект групповой синхронизации
func (сам *Ядро) Wg() types.IWgName {
	return сам.wg
}

// Контекст -- возвращает глобальный контекст приложения
func (сам *Ядро) Контекст() context.Context {
	return сам.ctxApp
}

// Done -- возвращает канал отмены контекста приложения
func (сам *Ядро) Done() <-chan struct{} {
	return сам.ctxApp.Done()
}

// Отменить -- отменяет глобальный контекст приложения
func (сам *Ядро) Отменить() {
	сам.блок.Lock()
	defer сам.блок.Unlock()
	сам.лог.Инфо("Kernel.CancelApp()\n")
	сам.fnCancel()
}

// Слог -- возвращает глобальный лог приложения
func (сам *Ядро) Слог() types.ИЛоггер {
	return сам.лог
}
