package service

import (
	commonConfig "cicv-data-closedloop/aarch64/pjisuv/common/config"
	commonService "cicv-data-closedloop/aarch64/pjisuv/common/service"
	"cicv-data-closedloop/common/config/c_log"
	"cicv-data-closedloop/common/domain"
	"cicv-data-closedloop/common/entity"
	"cicv-data-closedloop/common/util"
	"net"
	"time"
)

// RunTimeWindowProducerQueue 依次处理时间窗口，从data目录移动到copy目录
func RunTimeWindowProducerQueue() {
	c_log.GlobalLogger.Info("生产者队列goroutine - 启动")
	for {
		// 1 监控自杀信号
		select {
		case signal := <-commonService.ChannelKillMove:
			if signal == 1 {
				commonService.ChannelKillMove <- 1
				if len(entity.TimeWindowProducerQueue) == 0 {
					commonService.AddKillTimes("4")
					return
				}
			} else { //signal == 2
				commonService.AddKillTimes("4")
				return
			}
		default:
		}
		time.Sleep(time.Duration(1) * time.Second)
		// 2 处理
		if len(entity.TimeWindowProducerQueue) == 0 {
			continue
		}
		currentTimeWindow := entity.TimeWindowProducerQueue[0]                                         // 当前窗口
		bags, _ := util.ListAbsolutePathWithSuffixAndSort(commonConfig.CloudConfig.BagDataDir, ".bag") // data目录的bag包列表
		move := false
		bigger := false
		for _, bag := range bags {
			bagTime := util.GetBagTime(bag) // bag包对应的时间
			// 3 如果bag时间在窗口时间区间内，则从data移动到copy
			if util.BagTimeInInterval(bagTime, currentTimeWindow.TimeWindowBegin, currentTimeWindow.TimeWindowEnd) {
				domain.MoveFromDataToCopy(currentTimeWindow.FaultTime, commonConfig.CloudConfig.BagDataDir, bag, commonConfig.CloudConfig.BagCopyDir)
				move = true
			} else {
				// 4 如果已经生成了新的包，则当前窗口已经移动完成了
				if util.TimeCustom1GreaterEqualThanTimeCustom2(bagTime, currentTimeWindow.TimeWindowBegin) {
					bigger = true
					break
				}
			}
		}
		// 5 如果没有包可以供当前窗口移动，且已经生成了更新的包，则当前窗口已经可以上传
		if !move && bigger {
			currentTimeWindow.CanUpload = "yes"
			// 如果第一个已经大于了timeWindowEnd，则触发上传并删除
			domain.SupplyCopyBags(commonConfig.CloudConfig.BagDataDir, commonConfig.CloudConfig.BagCopyDir, currentTimeWindow)
			entity.RefreshTcpSendTime()
			go sendTimeWindowByTcp(currentTimeWindow)
			entity.RemoveHeadOfTimeWindowProducerQueue()
			entity.AddTimeWindowToTimeWindowConsumerQueue(currentTimeWindow)
			// 获取copy目录下的字典json，key为触发时间，value为label
			timeToLabelJson, _ := util.ReadFile(commonConfig.CloudConfig.TimeToLabelJsonPath)
			timeToLabelMap, _ := util.JsonStringToMap(timeToLabelJson)
			if timeToLabelMap == nil {
				timeToLabelMap = make(map[string]interface{})
			}
			timeToLabelMap[currentTimeWindow.FaultTime] = util.ToString(currentTimeWindow.Labels)
			timeToLabelJson, _ = util.MapToJsonString(timeToLabelMap)
			_ = util.WriteFile(timeToLabelJson, commonConfig.CloudConfig.TimeToLabelJsonPath)
			continue
		} else { // 保证当前窗口只发送一次，每间隔5秒发一次非yes窗口
			if int(time.Since(entity.TcpSendTime).Seconds()) > commonConfig.CloudConfig.TimeWindowSendGap {
				currentTimeWindow.CanUpload = "no"
				c_log.GlobalLogger.Info("每隔", commonConfig.CloudConfig.TimeWindowSendGap, "秒发送一次tcp消息")
				entity.RefreshTcpSendTime()
				go sendTimeWindowByTcp(currentTimeWindow)
			}
		}
	}
}

func sendTimeWindowByTcp(timeWindow entity.TimeWindow) {
	socket := commonConfig.CloudConfig.Hosts[1].Ip + ":" + commonConfig.CloudConfig.TcpPort
	tcpConn, err := net.Dial("tcp", socket)
	if err != nil {
		c_log.GlobalLogger.Error("建立tcp连接", socket, "失败：", err)
		return
	}
	defer tcpConn.Close()
	// 发送数据
	send, _ := entity.TimeWindowToJson(timeWindow)
	_, err = tcpConn.Write([]byte(send))
	if err != nil {
		c_log.GlobalLogger.Error("master发送给slave时间窗口", timeWindow, "失败：", err)
		return
	}
}
