package service

import (
	commonConfig "cicv-data-closedloop/aarch64/pji/common/config"
	"cicv-data-closedloop/common/config/c_log"
	"cicv-data-closedloop/common/util"
	"net/rpc"
	"os"
	"sync"
	"time"
)

var (
	ChannelKillRosRecord  = make(chan int)
	ChannelKillDiskClean  = make(chan int)
	ChannelKillSubscriber = make(chan int)
	ChannelKillMove       = make(chan int)
	ChannelKillConsume    = make(chan int)

	KillChannel = 5
	KillTimes   = 0
	MutexKill   sync.Mutex
)

// KillSignal 停止信号，主从节点接收到数据后准备重启
type KillSignal struct {
	NodeName       string
	DropUploadData bool
	Restart        bool
}

// KillService 定义要远程调用的类型和方法
type KillService struct{}

// Kill 杀死自身程序，通过通道实现 方法必须满足RPC规范：函数有两个参数，第一个参数是请求，第二个是响应
func (m *KillService) Kill(args KillSignal, reply *int) error {
	c_log.GlobalLogger.Info("接收到自杀信号：", args)
	// 1 杀死 rosbag record 命令
	ChannelKillRosRecord <- 1
	// 2 杀死所有 ros 订阅者
	ChannelKillSubscriber <- 1
	// 3 杀死上传任任务
	if args.DropUploadData == true {
		// 3-1 等待上传结束再杀死
		ChannelKillMove <- 1
		ChannelKillConsume <- 1
	} else {
		// 3-2 直接杀死
		ChannelKillMove <- 2
		ChannelKillConsume <- 2
	}
	go killDone(args.Restart)
	return nil
}
func WaitKillSelf() {
	killService := new(KillService)
	err := rpc.Register(killService)
	if err != nil {
		c_log.GlobalLogger.Error("注册rpc服务失败：", err)
		return
	}

	// 等待并处理远程调用请求
	for {
		conn, err := commonConfig.KillSignalListener.Accept()
		if err != nil {
			continue
		}
		go rpc.ServeConn(conn)
	}
}

func AddKillTimes(info string) {
	MutexKill.Lock()
	defer MutexKill.Unlock()
	switch info {
	case "1":
		ChannelKillDiskClean <- 1
		close(ChannelKillRosRecord)
		KillTimes++
		c_log.GlobalLogger.Infof("已杀死 record 打包 goroutine，当前自杀进度 %v / %v", KillTimes, KillChannel)
	case "2":
		close(ChannelKillDiskClean)
		KillTimes++
		c_log.GlobalLogger.Infof("已杀死 bag 包数量维护 goroutine，当前自杀进度 %v / %v", KillTimes, KillChannel)
	case "3":
		close(ChannelKillSubscriber)
		KillTimes++
		c_log.GlobalLogger.Infof("已杀死 rosnode 和ros 订阅者 goroutine，当前自杀进度 %v / %v", KillTimes, KillChannel)
	case "4":
		close(ChannelKillMove)
		KillTimes++
		c_log.GlobalLogger.Infof("已杀死 bag 包移动 goroutine，当前自杀进度 %v / %v", KillTimes, KillChannel)
	case "5":
		close(ChannelKillConsume)
		KillTimes++
		c_log.GlobalLogger.Infof("已杀死 bag 包消费 goroutine，当前自杀进度 %v / %v", KillTimes, KillChannel)
	}
}

func killDone(restart bool) {
	for {
		time.Sleep(time.Duration(1) * time.Second)
		if KillChannel == KillTimes {
			if restart {
				_, err := util.ExecuteWithPath(commonConfig.LocalConfig.RestartCmd.Dir, commonConfig.LocalConfig.RestartCmd.Name, commonConfig.LocalConfig.RestartCmd.Args...)
				if err != nil {
					c_log.GlobalLogger.Info("启动新程序失败,【path】=", commonConfig.LocalConfig.RestartCmd.Dir, "【cmd】=", commonConfig.LocalConfig.RestartCmd.Name, commonConfig.LocalConfig.RestartCmd.Args, "：", err)
					os.Exit(-1)
				}
				c_log.GlobalLogger.Info("数据采集任务更新，正常退出当前程序。")
			} else {
				c_log.GlobalLogger.Info("数据采集任务终止，正常退出当前程序。")
			}
			os.Exit(0)
		}
	}
}
