package rpc

import (
	"net"

	"gitlink.org.cn/cloudream/common/pkgs/async"
	"google.golang.org/grpc"
)

type ServerEventChan = async.UnboundChannel[RPCServerEvent]

type RPCServerEvent interface {
	IsRPCServerEvent()
}

type ExitEvent struct {
	RPCServerEvent
	Err error
}

type Config struct {
	Listen string `json:"listen"`
}

type ServerBase struct {
	cfg     Config
	grpcSvr *grpc.Server
	srvImpl any
	svcDesc *grpc.ServiceDesc
}

func NewServerBase(cfg Config, srvImpl any, svcDesc *grpc.ServiceDesc) *ServerBase {
	return &ServerBase{
		cfg:     cfg,
		srvImpl: srvImpl,
		svcDesc: svcDesc,
	}
}

func (s *ServerBase) Start() *ServerEventChan {
	ch := async.NewUnboundChannel[RPCServerEvent]()
	go func() {
		lis, err := net.Listen("tcp", s.cfg.Listen)
		if err != nil {
			ch.Send(&ExitEvent{Err: err})
			return
		}
		s.grpcSvr = grpc.NewServer()
		s.grpcSvr.RegisterService(s.svcDesc, s.srvImpl)
		err = s.grpcSvr.Serve(lis)
		ch.Send(&ExitEvent{Err: err})
	}()
	return ch
}

func (s *ServerBase) Stop() {
	if s.grpcSvr != nil {
		s.grpcSvr.Stop()
	}
}
