// package service -- главный тип сервиса шины данных
package service

import (
	"context"
	"fmt"
	"log"

	"p78git.ddns.net/svi/gobus/internal/dict_topic"
	"p78git.ddns.net/svi/gobus/internal/serv_grpc"
	"p78git.ddns.net/svi/gobus/pkg/types"
)

// Service -- главный тип сервиса шины данных
type Service struct {
	ctxBg     context.Context  // Неотменяемый контекст приложения
	ctx       context.Context  // Отменяемый контекст приложения
	fnCancel  func()           // Функция отмены контекста приложения
	dictTopic types.IDictTopic // Потокобезопасный словарь топиков
	servGrpc  *serv_grpc.ServGrpc
}

// NewSevice -- взвращае тновый сервис
func NewSevice() (*Service, error) {
	log.Printf("NewService()\n")
	sf := &Service{
		ctxBg: context.Background(),
	}
	sf.ctx, sf.fnCancel = context.WithCancel(sf.ctxBg)
	var err error
	sf.dictTopic, err = dict_topic.NewDictTopic()
	if err != nil {
		return nil, fmt.Errorf("NewService(): in create DictTopic, err=\n\t%w", err)
	}
	sf.servGrpc, err = serv_grpc.NewServGrpc(sf)
	if err != nil {
		return nil, fmt.Errorf("NewService(): in create ServGrpc, err=\n\t%w", err)
	}
	return sf, nil
}

// Run -- запускает сервис в работу
func (sf *Service) Run() error {
	log.Printf("Service.Run()\n")
	sf.servGrpc.Run()
	<-sf.ctx.Done()
	return nil
}

// Ctx -- возвращает контекст приложения
func (sf Service) Ctx() context.Context {
	return sf.ctx
}

// CancelApp -- отменяет контекст приложения
func (sf *Service) CancelApp() {
	sf.fnCancel()
}

// DictTopic -- возвращает потокобезопасный словарь топиков
func (sf *Service) DictTopic() types.IDictTopic {
	return sf.dictTopic
}
