package main

import (
	_ "net/http/pprof"
	"os/exec"
	"runtime"
	"time"

	jsoniter "github.com/json-iterator/go"
	"github.com/sirupsen/logrus"
	"github.com/thinkgos/timing/v3"

	"lc/common/util"
)

var json = jsoniter.ConfigCompatibleWithStandardLibrary

var pool *util.Pool
var IDGen util.IdWorker

var version = "1.4.1"
var appName = "ipole"

func Stat(args ...interface{}) interface{} {
	lastGC := time.Now()
	for {
		if time.Now().Sub(lastGC) > time.Minute {
			timing.Count()
			runtime.GC()
			lastGC = time.Now()
		}
		time.Sleep(time.Second)
	}
}

func GetNextUint64() uint64 {
	u64, err := IDGen.NextId()
	if err != nil {
		logrus.Errorf("IDGen.NextId发生错误:%s", err.Error())
		u64 = util.MlNow().Unix()
	}
	return uint64(u64)
}

// SyncTime 每半小时同步一次时间
func SyncTime(args ...interface{}) interface{} {
	for {
		err := exec.Command("ntpclient", "-h", "106.52.134.22", "-s").Run()
		if err != nil {
			logrus.Errorf("时间同步失败:%s", err.Error())
		} else {
			logrus.Info("时间同步成功,当前时间:", util.MlNow().String())
		}
		time.Sleep(30 * time.Minute)
	}
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU() * 2)

	util.InitLogrus("release")

	logrus.Infof("当前程序版本:%s", appName+" "+version)

	if err := loadAppConfig(); err != nil {
		logrus.Errorf("loadAppConfig错误:%s", err.Error())
		return
	}

	if err := loadSerialConfig(); err != nil {
		logrus.Errorf("loadAppConfig错误:%s", err.Error())
		return
	}

	_ = IDGen.InitIdWorker(1000, 1)

	GetMQTTMgr()

	InitRedis(&util.RedisConfig{Redis_Address: appConfig.Edge.Redis.Server, Redis_Password: appConfig.Edge.Redis.Password})
	defer UnInitRedis()

	//打开串口
	GetSerialMgr().AddSerialPorts(serialConfig.Serial)

	//创建设备并启动数据处理流程
	for k := range serialConfig.Serial {
		if devinfos, err := LoadDev(k); err == nil {
			GetDeviceMgr().AddDevices(devinfos)
		}
	}

	pool = util.NewPool(10)
	pool.Add(SyncTime, 0)

	pool.Add(WatchDevConfig, 1)
	pool.Add(WatchModelConfig, 2)
	pool.Add(WatchConfConfig, 3)
	pool.Add(GetMQTTMgr().MQTTMessageHandle, 4)
	pool.Add(GetMQTTMgr().MQTTConnectMgr, 5)
	pool.Add(Stat, 6)
	pool.Run()
	pool.Wait()
}
