package protocol

import (
	"bytes"
	"dlt645-server/errors"
	"encoding/binary"
	"encoding/json"
	"fmt"
	log "github.com/sirupsen/logrus"
	"reflect"
	"strconv"
)

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

type DHeader struct {
	MsgID MsgID
}

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

	}

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

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

// 协议解码
func (message *Message) Decode(data []byte) error {
	// 检验标志位
	length := len(data)
	if length == 0 {
		return errors.ErrInvalidMessage
	}
	if data[0] != ReceiveByte && data[0] != RegisterByte {
		return errors.ErrInvalidMessage
	}
	if  !message.checkSum(data){
		return errors.ErrInvalidCheckSum
	}
	var header Header
	var err error
	//处理注册包
	if data[0] == RegisterByte {

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

		//fmt.Println(header.Imei)
		//fmt.Println()

		header.IccID, err = strconv.ParseUint(header.Imei, 10, 64)
		header.MsgID = 0x0040 //消息ID
		if err == nil {
			message.Body = nil
		} else {
			log.WithFields(log.Fields{
				"id":     fmt.Sprintf("0x%x", header.MsgID),
				"reason": err,
			}).Warn("failed to decode message")
		}
		message.Header = header
		return nil
	} else if len(data) < 8 {
		log.WithFields(log.Fields{
			"data":   fmt.Sprintf("V:%v", data),
			"reason": "error datalen",
		}).Warn("failed to decode message")
	} else {
		header.MsgID = MsgID(binary.BigEndian.Uint32(data[10:15]))      //消息ID
		entity, _, err := message.decode(uint32(header.MsgID), data[:]) //解析实体对象 entity     buffer : 为消息标识
		if err == nil {
			message.Body = entity
		} else {
			log.WithFields(log.Fields{
				"id":     fmt.Sprintf("0x%x", header.MsgID),
				"reason": err,
			}).Warn("failed to decode message")
		}
	}

	message.Header = header
	return nil
}

//--->
func (message *Message) decode(dataType uint32, data []byte) (Entity, int, error) {
	creator, ok := entityMapper[dataType]
	if !ok {
		return nil, 0, errors.ErrTypeNotRegistered
	}

	entity := creator()

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

// 写入二进制数据
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
}
