package protocol

import (
	"bytes"
	"dlt645-server/errors"
	"encoding/binary"
	"encoding/json"
	"github.com/gogf/gf/os/glog"
	"reflect"
	"strconv"
)

// 消息包
type Message struct {
	Header Header
	Body   Entity
}

type DHeader struct {
	MsgID MsgID
}

type Data struct {
	PowerData
	VIData
}

type PowerData struct {
	ActivePower float64 `json:"active_power"`
}

type VIData struct {
	AV float64 `json:"av"` // A相电压
	AI float64 `json:"ai"` // A相电流
	BV float64 `json:"bv"` // B相电压
	BI float64 `json:"bi"` // B相电流
	CV float64 `json:"cv"` // C相电压
	CI float64 `json:"ci"` // C相电流
}

// 协议编码
func (message *Message) Encode() ([]byte, error) {
	// 编码消息体
	var err error
	var data []byte
	if message.Body != nil && !reflect.ValueOf(message.Body).IsNil() {
		data, err = message.Body.Encode(nil)
		if err != nil {
			return nil, err
		}

	}

	// 二进制转义
	buffer := bytes.NewBuffer(nil)

	message.write(buffer, data)
	return buffer.Bytes(), nil
}

// 协议解码
func (message *Message) Decode(ctx *PacketContext, data []byte) (result Data, err error) {
	// 检验标志位
	length := len(data)
	if length == 0 {
		return result, errors.ErrInvalidMessage
	}
	for i := 0; i <= length; i++ {
		if data[i] == SendByte {
			continue
		} else {
			data = data[i:length]
			glog.Debugf("收到数据：%2X", data)
			break
		}
	}
	if data[0] != ReceiveByte {
		return result, nil
	}
	if data[len(data)-1] != EndByte {
		data = append(data, 0x16)
	}
	if !message.checkSum(data) {
		return result, errors.ErrInvalidCheckSum
	}

	//处理注册包
	if data[0] == RegisterByte {

		header := Header{}
		_ = json.Unmarshal(data, &header)

		header.IccID, err = strconv.ParseUint(header.Imei, 10, 64)
		header.MsgID = 0x0040 //消息ID
		if err != nil {
			if err != nil {
				glog.Errorf("解析报文失败:%s", err.Error())
			}
		}
		message.Body = nil
		message.Header = header
		return result, nil
	}
	if len(data) < 8 {
		if err != nil {
			glog.Errorf("解析报文失败:%s", errors.ErrInvalidBody)
		}
	}
	if data[8] == 0x93 {
		result, err = message.decode(ctx, uint32(0x93), data[:])
		if err != nil {
			glog.Errorf("解析报文失败:%s", err.Error())
		}

	} else {
		msgID := MsgID(binary.BigEndian.Uint32(data[10:15]))      //消息ID
		result, err = message.decode(ctx, uint32(msgID), data[:]) //解析实体对象 entity     buffer : 为消息标识
		if err != nil {
			glog.Errorf("解析报文失败:%s", err.Error())
		}
	}
	return result, nil
}

//--->
func (message *Message) decode(ctx *PacketContext, dataType uint32, data []byte) (result Data, err error) {
	creator, ok := entityMapper[dataType]
	if !ok {
		return result, errors.ErrTypeNotRegistered
	}

	entity := creator()

	result, err = entity.Decode(ctx, data) //解析data数据
	if err != nil {
		return result, err
	}
	return result, err
}

// 写入二进制数据
func (message *Message) write(buffer *bytes.Buffer, data []byte) *Message {
	for _, b := range data {
		if b == PrefixID {
			buffer.WriteByte(EscapeByte)
			buffer.WriteByte(EscapeByteSufix2)
		} else if b == EscapeByte {
			buffer.WriteByte(EscapeByte)
			buffer.WriteByte(EscapeByteSufix1)
		} else {
			buffer.WriteByte(b)
		}
	}
	return message
}

// 和校验
func (message *Message) checkSum(data []byte) bool {
	var checkSum byte
	for _, b := range data[:len(data)-2] {
		checkSum += b
	}
	checkSum = checkSum & 0xFF

	if checkSum == data[len(data)-2] {
		return true
	}
	return false
}
