package main

import (
	"context"
	"net/http"
	"time"

	"../log"
	"github.com/gorilla/mux"
	"github.com/gorilla/rpc"
	"github.com/gorilla/rpc/json"
	"go.uber.org/zap"
)

// 创建一个 HTTP RPC server
// 这个不是通用的函数，适合逻辑紧密绑定的
// @addr rpc 服务地址
// @chQuit rpc 服务退出通知。如果外部关闭 chQuit，rpc server 退出。
// 初级版本实现粗糙了一点
func createRpcServer(addr string, chQuit <-chan struct{}) error {
	rpc_server := rpc.NewServer()
	rpc_server.RegisterCodec(json.NewCodec(), "application/json")

	err := rpc_server.RegisterService(new(RpcService), "")
	if nil != err {
		return err
	}

	router := mux.NewRouter()
	router.Handle("/rpc", rpc_server)

	http_server := &http.Server{
		Addr:         addr,
		Handler:      router,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	log.Debug("rpc", zap.String("addr", addr))
	go func() {
		if err := http_server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Warn("rpc server listen error:", zap.String("addr", addr), zap.Error(err))
		}
	}()

	go func() {
		select {
		case <-chQuit:
		}

		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()

		if err := http_server.Shutdown(ctx); err != nil {
			log.Warn("rpc server shutdown error", zap.Error(err))
		}
		select {
		case <-ctx.Done():
			log.Info("rpc server shutdown timeout")
		}
		log.Info("rpc server quit.")
	}()

	return nil
}
