package main

import (
	"context"
	"net/http"
	"os"
	"os/signal"
	"syscall"
	"time"

	"mtp2_if/config"
	"mtp2_if/db"
	"mtp2_if/logger"
	"mtp2_if/rediscli"
	"mtp2_if/routers"

	"github.com/DeanThompson/ginpprof"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/mattn/go-oci8"
)

// @title MTP2.0 查询服务 API
// @version 1.0
// @description 新的查询服务，替代原通用查询服务。游客Token：c886a057f3d820d4dbc41473686c7c2d
// @termsOfService http://www.muchinfo.cn
//
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
//
// @BasePath /api
func main() {
	// 初始化配置
	err := config.SerCfg.Init("config/config.xml")
	if err != nil {
		println("read config file failed:", err)
		return
	}

	// 初始化日志组件
	err = logger.Init(config.SerCfg.GetLogSetting())
	if err != nil {
		println("init logger failed:", err)
		return
	}

	// 初始化数据库引擎
	err = db.InitDbEngine()
	if err != nil {
		logger.GetLogger().Errorf("init db engine failed:", err.Error())
		return
	}
	go db.StartCheckConnection(0)
	defer db.Close()

	// 初始化MongoDB引擎
	err = db.InitMongoDB()
	if err != nil {
		logger.GetLogger().Errorf("init mongodb engine failed:", err.Error())
		return
	}
	go db.StartCheckConnection(2)
	defer db.CloseMongoDB()

	// 初始化MySQL引擎
	err = db.InitMySQLDbEngine()
	if err != nil {
		logger.GetLogger().Errorf("init mysql engine failed:", err.Error())
		return
	}
	go db.StartCheckConnection(1)
	defer db.CloseMySQL()

	// 初始化Redis客户端
	err = rediscli.InitRedisCli()
	if err != nil {
		logger.GetLogger().Errorf("init redis client failed:", err.Error())
		return
	}
	defer rediscli.CloseReidsClient()

	if config.SerCfg.GetDebugMode() {
		gin.SetMode(gin.DebugMode)
	} else {
		gin.SetMode(gin.ReleaseMode)
	}

	// 设置超时
	timeout := 15 * time.Second

	// 初始化路由
	r := routers.InitRouter()

	// doubg模式启用pprof
	if config.SerCfg.GetDebugMode() {
		dm := r.Group("/debug/pprof")
		ginpprof.WrapGroup(dm)
		timeout = 60 * time.Second
	}

	// 声明web服务
	webser := &http.Server{
		Handler:      r,
		Addr:         config.SerCfg.GetWebListenAddr(),
		WriteTimeout: timeout,
		ReadTimeout:  timeout,
	}

	cxt, cancel := context.WithCancel(context.Background())
	defer cancel()

	// 启动服务
	c := make(chan struct{}, 1)
	go func() {
		defer close(c)
		if err := webser.ListenAndServe(); err != nil {
			logger.GetLogger().Errorf("Start service failed[%s].", err.Error())
			c <- struct{}{}
		}
	}()

	// 信号控制
	s := make(chan os.Signal, 1)
	signal.Notify(s, syscall.SIGINT, syscall.SIGTERM)
	select {
	case <-s:
		logger.GetLogger().Debug("Shutdown service...")
		timeCxt, tCancel := context.WithTimeout(cxt, 5*time.Second)
		defer tCancel()

		if err := webser.Shutdown(timeCxt); err != nil {
			logger.GetLogger().Errorf("Shutdown service failed: %s", err.Error())
		}
	case <-c:

	}

	signal.Stop(s)
	defer close(s)
	logger.GetLogger().Debug("Service stopped")
}
