package server

import (
	"context"
	"demo-server/internal/config"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net"
	"net/http"
)

type Server struct {
	cfg *config.Configuration
	engine *gin.Engine
	httpSvr *http.Server
}

var (
	svr *Server
)

func GetSvr() *Server {
	return svr
}

func New(cfg *config.Configuration) *Server {
	s := &Server{
		cfg: cfg,
	}
	s.Init()

	svr = s
	return s
}

func (s *Server) Run() {
	if err := s.httpSvr.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		panic(err)
	}
}

func (s *Server) Shutdown(ctx context.Context) (err error) {
	if s.httpSvr == nil {
		return
	}
	err = s.httpSvr.Shutdown(ctx)
	return
}

func (s *Server) SvrRunSuccessMsg() {
	svr := s.cfg.Svr
	printIPInfo := func(adds ...string) {
		info := "svr running, via"
		for _, add := range adds {
			info += "\n\thttp://" + add
		}
		if len(adds) > 0 {
			info += "\n\tvia doc at http://" + adds[0] + "/swagger"
		}
		zap.S().Info(info)
	}
	ip, port, _ := net.SplitHostPort(svr.Address)
	adders, err := net.InterfaceAddrs()
	if net.ParseIP(ip).IsUnspecified() && err == nil {
		var successAddress []string
		for _, addr := range adders {
			if ipNet, ok := addr.(*net.IPNet); ok && (ipNet.IP.IsPrivate()) {
				successAddress = append(successAddress, net.JoinHostPort(ipNet.IP.String(), port))
			}
		}
		printIPInfo(successAddress...)
	} else {
		printIPInfo(svr.Address)
	}
}

func (s *Server) GetCfg() *config.Configuration {
	return s.cfg
}

// Dispatch 当配置文件更新的时候可以去调用
// 目前使用的全局 config 指针的方式如果发生更改,理论上 server 关联的 model 内置指针对象也会被更改
// 需要重新初始化的部分将由本函数予以实现
func (s *Server) Dispatch(_ *config.Configuration) {
}