package protocol

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

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

type DHeader struct {
	MsgID MsgID
}

type Data struct {
	DataType int
	PowerData
	VIData
	IData
}

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

type VIData struct {
	AV float64 `json:"av"` // A相电压
	BV float64 `json:"bv"` // B相电压
	CV float64 `json:"cv"` // C相电压
}

type IData struct {
	AI float64 `json:"ai"` // A相电流
	BI float64 `json:"bi"` // B相电流
	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, buf []byte) (data Data, err error) {
	// 检验标志位
	length := len(buf)
	if length == 0 {
		return data, errors.ErrInvalidMessage
	}
	for i := 0; i <= length; i++ {
		if buf[i] == SendByte {
			continue
		} else {
			buf = buf[i:length]
			glog.Debugf("收到数据：%2X", buf)
			break
		}
	}
	if buf[0] != ReceiveByte {
		return data, nil
	}
	if buf[len(buf)-1] != EndByte {
		buf = append(buf, 0x16)
	}
	if !message.checkSum(buf) {
		return data, errors.ErrInvalidCheckSum
	}

	if len(buf) < 8 {
		if err != nil {
			glog.Errorf("解析报文失败:%s", errors.ErrInvalidBody)
		}
	}
	if buf[8] == 0x93 {
		data, err = message.decode(ctx, uint32(0x93), buf[:])
		if err != nil {
			glog.Errorf("解析报文失败:%s", err.Error())
		}

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

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

	entity := creator()
	data, err = entity.Decode(ctx, buf) //解析data数据
	if err != nil {
		return data, err
	}
	return data, 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
}
