package grpc

import (
	"context"
	"net"
	"os"
	"os/signal"

	v1 "gitlab.com/gitlab-org/spamcheck/api/v1"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"gitlab.com/gitlab-org/labkit/log"
	grpctracing "gitlab.com/gitlab-org/labkit/tracing/grpc"
	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
)

// RunServer runs gRPC service to publish SpamCheck service
func RunServer(ctx context.Context, v1API v1.SpamcheckServiceServer, port string) error {
	listen, err := net.Listen("tcp", ":"+port)
	if err != nil {
		return err
	}

	// register service with a set of interceptors configured (metrics & tracing)
	opts := []grpc.ServerOption{
		grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
			grpc_prometheus.UnaryServerInterceptor,
			grpctracing.UnaryServerTracingInterceptor(),
		)),
	}
	server := grpc.NewServer(opts...)
	
	v1.RegisterSpamcheckServiceServer(server, v1API)

	// register the server with the reflection service for CLI use
	// TODO make this development only (?)
	reflection.Register(server)

	// graceful shutdown
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for range c {
			// sig is a ^C, handle it
			log.Info("shutting down gRPC server...")

			server.GracefulStop()

			<-ctx.Done()
		}
	}()

	// start gRPC server
	log.Info("Starting gRPC server...")
	return server.Serve(listen)
}
