package objs

import (
	"fmt"
	"strconv"

	"com.zkh/agent/coap/utils"
	"github.com/plgd-dev/go-coap/v3/message"
)

const (
	// SESSION_ID APP与Gateway和Device之间或Device与Gateway之间的请求或回应,都需要通过此Option附带创建会话时生成的会话ID。
	SESSION_ID message.OptionID = 2048

	// PUUID 手机APP的唯一标识,可以由APP随机生成的UUID。APP登陆其它账号时,需要重新为该账号重启生成UUID。
	PUUID message.OptionID = 2056
	// PLUGIN 插件名称,插件管理密钥协商通道采用本地控制通道,添加此Option标识出是哪个插件进行密钥协商
	PLUGIN message.OptionID = 2057
	// LOCAL_ER 本地控制失败错误码,返回给APP,当前仅在会话失效场景下,给APP返回1的错误码,其他控制失败的场景,不会给APP返回响应消息。
	LOCAL_ER message.OptionID = 2058

	// SEQ_NUM_ID 发送报文的序列号,每个会话建立时,会协商出对端在该会话上的请求序列号;后续通过该会话给对端发送报文时,每个报文都必须在此Option中带上序列号的值,每个报文需增加一次序列号。
	// 无符号整型,参考CoAP协议中对uint的定义,报文中Integer值使用网络序存放。
	SEQ_NUM_ID message.OptionID = 2053
	// ACCESS_TOKEN_ID Gateway或Device给云端发送请求或回应时,每个报文都需要在此Option中附带登录时生成的accessToken。
	ACCESS_TOKEN_ID message.OptionID = 2049
	// REQ_ID 云端发给Gateway或Device时(事件接口除外),都会附带此字段;Gateway或Device不需要理解此Option的内容,只需要在回应时原封不动的返回此字段值即可。
	REQ_ID message.OptionID = 2050
	// DEV_ID 云端发给Gateway或Device时(事件接口除外),都会附带此字段;Gateway或Device不需要理解此Option的内容,只需要在回应时原封不动的返回此字段值即可。
	DEV_ID message.OptionID = 2051
	// USER_ID 云端发给Gateway或Device时(事件接口除外),都会附带此字段;Gateway或Device不需要理解此Option的内容,只需要在回应时原封不动的返回此字段值即可。
	USER_ID message.OptionID = 2052
	// CLIENT_ID 端侧将udid做sha256后做hex编码(小写)传给云端。
	CLIENT_ID message.OptionID = 3000
	// APP_ID 业务标识,用于云侧区分不同业务。
	APP_ID message.OptionID = 3001
)

func init() {
	message.CoapOptionDefs[SESSION_ID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 16}
	message.CoapOptionDefs[SEQ_NUM_ID] = message.OptionDef{ValueFormat: message.ValueUint, MinLen: 0, MaxLen: 4}
	message.CoapOptionDefs[PUUID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 17}
	message.CoapOptionDefs[PLUGIN] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 32}
	message.CoapOptionDefs[LOCAL_ER] = message.OptionDef{ValueFormat: message.ValueUint, MinLen: 0, MaxLen: 4}

	message.CoapOptionDefs[ACCESS_TOKEN_ID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 40}
	message.CoapOptionDefs[REQ_ID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 256}
	message.CoapOptionDefs[DEV_ID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 256}
	message.CoapOptionDefs[USER_ID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 256}
	message.CoapOptionDefs[CLIENT_ID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 64}
	message.CoapOptionDefs[APP_ID] = message.OptionDef{ValueFormat: message.ValueString, MinLen: 0, MaxLen: 10}

}

func MapToOptions(data map[string]string) message.Options {
	opts := message.Options{}
	if data["DEV_ID"] != "" {
		opts = opts.Add(message.Option{ID: DEV_ID, Value: []byte(data["DEV_ID"])})
	}
	if data["ACCESS_TOKEN_ID"] != "" {
		opts = opts.Add(message.Option{ID: ACCESS_TOKEN_ID, Value: []byte(data["ACCESS_TOKEN_ID"])})
	}
	if data["REQ_ID"] != "" {
		opts = opts.Add(message.Option{ID: REQ_ID, Value: []byte(data["REQ_ID"])})
	}
	if data["USER_ID"] != "" {
		opts = opts.Add(message.Option{ID: USER_ID, Value: []byte(data["USER_ID"])})
	}
	if data["CLIENT_ID"] != "" {
		opts = opts.Add(message.Option{ID: CLIENT_ID, Value: []byte(data["CLIENT_ID"])})
	}

	if data["APP_ID"] != "" {
		opts = opts.Add(message.Option{ID: APP_ID, Value: []byte(data["APP_ID"])})
	}

	if data["SEQ_NUM_ID"] != "" {
		seqID, _ := strconv.Atoi(data["SEQ_NUM_ID"])

		opts = opts.Add(message.Option{ID: SEQ_NUM_ID, Value: utils.IntToBytes(seqID)})
	}

	return opts
}
func OptionsToMap(opts message.Options) map[string]string {
	data := make(map[string]string)

	temp, err := opts.GetString(DEV_ID)
	if err == nil {
		data["DEV_ID"] = temp
	}
	temp, err = opts.GetString(REQ_ID)
	if err == nil {
		data["REQ_ID"] = temp
	}
	temp, err = opts.GetString(ACCESS_TOKEN_ID)
	if err == nil {
		data["ACCESS_TOKEN_ID"] = temp
	}
	temp, err = opts.GetString(USER_ID)
	if err == nil {
		data["USER_ID"] = temp
	}
	temp, err = opts.GetString(CLIENT_ID)
	if err == nil {
		data["CLIENT_ID"] = temp
	}
	temp, err = opts.GetString(APP_ID)
	if err == nil {
		data["APP_ID"] = temp
	}

	// strTmp := make([]string, 20)
	// temp2, _ := opts.GetStrings(message.URIPath, strTmp)
	// log.Printf("URIPath:%s   \n", strTmp[:temp2])

	temp1, err := opts.GetUint32(SEQ_NUM_ID)
	if err == nil {
		data["SEQ_NUM_ID"] = fmt.Sprintf("%d", temp1)
	}

	return data
}