package main

import (
	"lc/common/models"
	"math"
	"sync"
	"time"

	"github.com/thinkgos/timing/v3"

	"lc/common/protocol"
	"lc/common/util"
)

func Precision(f float64, prec int, round bool) float64 {
	pow10N := math.Pow10(prec)
	if round {
		return math.Trunc((f+0.5/pow10N)*pow10N) / pow10N
	}
	return math.Trunc((f)*pow10N) / pow10N
}

var mapRtuUploadManager sync.Map

type RtuUploadManager struct {
	DataLock sync.Mutex
	DevInfo  *protocol.DevInfo
	DateTime time.Time
	Data     map[uint16]float64
	Timer    *timing.Timing
}

func NewRtuUploadManager(rtuinfo *protocol.DevInfo) *RtuUploadManager {
	o := RtuUploadManager{
		DevInfo: rtuinfo,
		Data:    make(map[uint16]float64),
		Timer:   timing.New().Run(),
	}

	o.Timer.AddJobFunc(o.SendData, time.Duration(o.DevInfo.SendCloud)*time.Millisecond)
	return &o
}

func (o *RtuUploadManager) Stop() {
	o.Timer.Close()
	o.DataLock.Lock()
	defer o.DataLock.Unlock()
	o.DevInfo = nil
	o.Data = nil
}

func (o *RtuUploadManager) AddData(data map[uint16]float64) {
	o.DataLock.Lock()
	defer o.DataLock.Unlock()

	for k, v := range data {
		o.Data[k] = v
	}
	o.DateTime = util.MlNow()
}

func (o *RtuUploadManager) SendData() {
	o.DataLock.Lock()
	defer func() {
		o.Data = make(map[uint16]float64)
		o.DataLock.Unlock()
		o.Timer.AddJobFunc(o.SendData, time.Duration(o.DevInfo.SendCloud)*time.Millisecond)
	}()
	if len(o.Data) == 0 {
		return
	}

	var obj protocol.Pack_UploadData
	if str, err := obj.EnCode(o.DevInfo.DevCode, appConfig.GID, GetNextUint64(), nil, o.DevInfo.TID, o.Data); err == nil {
		topic := GetTopic(o.GetDevType(), o.DevInfo.DevCode, protocol.TP_MODBUS_DATA)
		GetMQTTMgr().Publish(topic, str, 0, ToAll) //上传消息 modbus rtu
	}
}

func (o *RtuUploadManager) GetDevType() string {
	if o.DevInfo.DevType == 1 {
		return protocol.DT_CONCENTRATOR
	} else if o.DevInfo.DevType == 2 {
		return protocol.DT_ENVIRONMENT
	} else if o.DevInfo.DevType == 4 {
		return protocol.DT_LIQUID
	} else if o.DevInfo.DevType == 5 {
		return protocol.DT_ROAD_COND
	} else if o.DevInfo.DevType == uint8(models.CableGuardian) {
		return protocol.DT_CableGuardian
	}
	return "unknown"
}
