package config

import (
	"cicv-data-closedloop/aarch64/kinglong/common/config"
	"cicv-data-closedloop/common/config/c_log"
	"cicv-data-closedloop/common/util"
	"cicv-data-closedloop/kinglong_msgs"
	entity "cicv-data-closedloop/kinglong_param"
	"github.com/bluenviron/goroslib/v2/pkg/msgs/std_msgs"
	"plugin"
	"strconv"
)

var (
	// 扩展
	TopicOfCicvExtend = "/cicv_extend"
	RuleOfCicvExtend  []func(param entity.KinglongParam) string

	// 1
	TopicOfNodeFaultInfo = "/nodefault_info"
	RuleOfNodefaultInfo  []func(data *kinglong_msgs.FaultInfo) string
	// 2
	TopicOfCicvLocation = "/cicv_location"
	RuleOfCicvLocation  []func(data *kinglong_msgs.PerceptionLocalization) string
	// 3
	TopicOfTpperception = "/tpperception"
	RuleOfTpperception  []func(data *kinglong_msgs.PerceptionObjects, param entity.KinglongParam) string
	// 4
	TopicOfFaultInfo = "/fault_info"
	RuleOfFaultInfo  []func(data *kinglong_msgs.FaultVec) string
	// 5
	TopicOfDataRead = "/data_read"
	RuleOfDataRead  []func(data *kinglong_msgs.Retrieval) string
	// 6
	TopicOfJinlongControlPub = "/jinlong_control_pub"
	RuleOfJinlongControlPub  []func(data *kinglong_msgs.JinlongControlCommand) string
	// 7
	TopicOfFailureLidar = "/failure/lidar"
	RuleOfFailureLidar  []func(data *std_msgs.Bool) string
	// 8
	TopicOfFailureRadar = "/failure/radar"
	RuleOfFailureRadar  []func(data *std_msgs.Bool) string
	// 9
	TopicOfFailureCamera = "/failure/camera"
	RuleOfFailureCamera  []func(data *std_msgs.Bool) string

	LabelMapTriggerId = make(map[string]string)
)

func InitTriggerConfig() {
	c_log.GlobalLogger.Info("主节点加载触发器插件 - 开始。")
	// 下载所有触发器的文件
	for _, trigger := range config.PlatformConfig.TaskTriggers {
		triggerLocalPath := config.CloudConfig.TriggersDir + trigger.TriggerScriptPath
		_ = util.CreateParentDir(triggerLocalPath)
		c_log.GlobalLogger.Info("下载触发器插件从 ", trigger.TriggerScriptPath, " 到 ", triggerLocalPath)
		config.OssMutex.Lock()
		err := config.OssBucket.GetObjectToFile(trigger.TriggerScriptPath, triggerLocalPath)
		config.OssMutex.Unlock()
		if err != nil {
			c_log.GlobalLogger.Error("下载 oss 上的触发器插件失败：", err)
			continue
		}
		// 载入插件到数组
		open, err := plugin.Open(triggerLocalPath)
		if err != nil {
			c_log.GlobalLogger.Error("加载本地插件", triggerLocalPath, "失败。", err)
			continue
		}
		topic0, err := open.Lookup("Topic")
		if err != nil {
			c_log.GlobalLogger.Error("加载本地插件", triggerLocalPath, "中的Topic方法失败。", err)
			continue
		}
		topic1, ok := topic0.(func() string)
		if ok != true {
			c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func() string):", err)
			continue
		}
		topic2 := topic1()
		rule, err := open.Lookup("Rule")
		if err != nil {
			c_log.GlobalLogger.Error("加载本地插件", triggerLocalPath, "中的Rule方法失败。", err)
			continue
		}
		if TopicOfCicvExtend == topic2 { // 自定义扩展
			f, ok := rule.(func(param entity.KinglongParam) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(param entity.ExtendParam):", err)
				continue
			}
			RuleOfCicvExtend = append(RuleOfCicvExtend, f)
		} else if TopicOfNodeFaultInfo == topic2 { // 1
			f, ok := rule.(func(data *kinglong_msgs.FaultInfo) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *kinglong_msgs.FaultInfo) string):", err)
				continue
			}
			RuleOfNodefaultInfo = append(RuleOfNodefaultInfo, f)
		} else if TopicOfCicvLocation == topic2 { // 2
			f, ok := rule.(func(data *kinglong_msgs.PerceptionLocalization) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *kinglong_msgs.PerceptionLocalization) string):", err)
				continue
			}
			RuleOfCicvLocation = append(RuleOfCicvLocation, f)
		} else if TopicOfTpperception == topic2 { // 3
			f, ok := rule.(func(data *kinglong_msgs.PerceptionObjects, param entity.KinglongParam) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *kinglong_msgs.PerceptionObjects, param entity.KinglongParam) string):", err)
				continue
			}
			RuleOfTpperception = append(RuleOfTpperception, f)
		} else if TopicOfFaultInfo == topic2 { // 4
			f, ok := rule.(func(data *kinglong_msgs.FaultVec) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *kinglong_msgs.FaultVec) string):", err)
				continue
			}
			RuleOfFaultInfo = append(RuleOfFaultInfo, f)
		} else if TopicOfDataRead == topic2 { // 5
			f, ok := rule.(func(data *kinglong_msgs.Retrieval) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *kinglong_msgs.Retrieval) string):", err)
				continue
			}
			RuleOfDataRead = append(RuleOfDataRead, f)
		} else if TopicOfJinlongControlPub == topic2 { // 6
			f, ok := rule.(func(data *kinglong_msgs.JinlongControlCommand) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *std_msgs.Bool) string):", err)
				continue
			}
			RuleOfJinlongControlPub = append(RuleOfJinlongControlPub, f)
		} else if TopicOfFailureLidar == topic2 { // 7
			f, ok := rule.(func(data *std_msgs.Bool) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *std_msgs.Bool) string):", err)
				continue
			}
			RuleOfFailureLidar = append(RuleOfFailureLidar, f)
		} else if TopicOfFailureRadar == topic2 { // 8
			f, ok := rule.(func(data *std_msgs.Bool) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *std_msgs.Bool) string):", err)
				continue
			}
			RuleOfFailureRadar = append(RuleOfFailureRadar, f)
		} else if TopicOfFailureCamera == topic2 { // 9
			f, ok := rule.(func(data *std_msgs.Bool) string)
			if ok != true {
				c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *kinglong_msgs.JinlongControlCommand) string):", err)
				continue
			}
			RuleOfFailureCamera = append(RuleOfFailureCamera, f)
		} else {
			c_log.GlobalLogger.Error("未知的topic：", topic2)
			continue
		}

		label, err := open.Lookup("Label")
		if err != nil {
			c_log.GlobalLogger.Error("加载本地插件 ", triggerLocalPath, " 中的 Label 方法失败。", err)
			continue
		}
		labelFunc := label.(func() string)
		labelString := labelFunc()
		LabelMapTriggerId[labelString] = strconv.Itoa(trigger.TriggerId)
		c_log.GlobalLogger.Info("主节点加载触发器插件：【ros topic】=", topic2, "，【触发器label】=", labelString, "【触发器ID】=", trigger.TriggerId)
	}
	c_log.GlobalLogger.Infof("一共有%v个触发器，【label和id映射关系】=%v", len(config.PlatformConfig.TaskTriggers), LabelMapTriggerId)
}
