// package serv_grpc -- сервер GRPC-запросов шины данных
package serv_grpc

import (
	"fmt"
	"io"
	"log"
	"net"
	"os"

	"google.golang.org/grpc"

	"p78git.ddns.net/svi/gobus/internal/serv_grpc/serv_get"
	"p78git.ddns.net/svi/gobus/internal/serv_grpc/serv_public"
	"p78git.ddns.net/svi/gobus/internal/serv_grpc/serv_subcsribe"
	"p78git.ddns.net/svi/gobus/internal/serv_grpc/serv_subscribe_buffer"
	"p78git.ddns.net/svi/gobus/internal/serv_grpc/serv_sync"
	"p78git.ddns.net/svi/gobus/pkg/net/netapi"
	"p78git.ddns.net/svi/gobus/pkg/types"
)

// ServGrpc -- сервер GRPC-запросов шины данных
type ServGrpc struct {
	netapi.UnsafeGoBusServer
	srv  net.Listener
	port string
	*serv_get.ServGet
	*serv_public.ServPublic
	*serv_sync.ServSync
	*serv_subcsribe.ServSubscribe
	*serv_subscribe_buffer.ServSubscribeBuffer
}

// NewServGrpc -- возвращает новый GRPC-сервер шины данных
func NewServGrpc(serv types.IService) (*ServGrpc, error) {
	log.Printf("NewServGrpc()\n")
	if serv == nil {
		return nil, fmt.Errorf("NewServGrpc(): IService==nil")
	}
	port := os.Getenv("SERV_GRPC_PORT")
	if port == "" {
		return nil, fmt.Errorf("NewServGrpc(): env SERV_GRPC_PORT not set")
	}
	sf := &ServGrpc{
		port: port,
	}
	var err error
	sf.ServPublic, err = serv_public.NewServPublic(serv)
	if err != nil {
		return nil, fmt.Errorf("NewServGrpc(): in create ServPublic, err=\n\t%w", err)
	}
	sf.ServSubscribe, err = serv_subcsribe.NewServSubscribe(serv)
	if err != nil {
		return nil, fmt.Errorf("NewServGrpc(): in create ServSubscribe, err=\n\t%w", err)
	}
	_ = netapi.GoBusServer(sf)
	return sf, nil
}

// Run -- запускает GRPC-сервер в работу
func (sf *ServGrpc) Run() {
	log.Printf("ServGrpc.Run()\n")
	go sf.listen()
}

// Слушает порт
func (sf *ServGrpc) listen() {
	var err error
	sf.srv, err = net.Listen("tcp", ":"+sf.port)
	if err != nil {
		log.Printf("ServGrpc.listen(): failed to listen, err=\n\t%v\n", err)
		return
	}
	opts := []grpc.ServerOption{}
	grpcServer := grpc.NewServer(opts...)
	netapi.RegisterGoBusServer(grpcServer, sf)
	err = grpcServer.Serve(sf.srv)
	if err != nil && err != io.EOF {
		strErr := fmt.Sprintf("ServGrpc.listen(): failed to listen, err=\n\t%v\n", err)
		log.Printf("ServGrpc.listen(): ошибка при работе GRPC-сервера, err=\n\t%v\n", strErr)
	}
	log.Printf("ServGrpc.listen(): работа сервера завершена")
}
