package zigbee

import (
	"encoding/binary"

	"github.com/valyala/bytebufferpool"
)

type PackGetPid struct {
	M1Flag uint16 //固定为F1F1
	M1Leng uint16 //包体1长度
	M1Cmd  uint8  //1字节
	M1Crc  uint16 //整包CRC
}

func (o *PackGetPid) EnCode() (*bytebufferpool.ByteBuffer, error) {
	buff := bytebufferpool.Get()
	buff.Write([]byte{0xF1, 0xF1}) //M1Flag uint16  //固定为F1F1
	tmp := make([]byte, 2)
	binary.BigEndian.PutUint16(tmp, 0)
	buff.Write(tmp)           //M1Leng   uint16  //包体1长度
	buff.WriteByte(CmdGetPid) //M1Cmd      uint8   //1字节
	//crc1
	crc16 := CRC16(buff.B)
	tmp2 := make([]byte, 2)
	binary.BigEndian.PutUint16(tmp2, crc16)
	buff.Write(tmp2) //外层CRC16
	return buff, nil
}

func (o *PackGetPid) DeCode(Data []byte) error {
	if len(Data) < 7 {
		return ErrorProtocol
	}
	if Data[0] != 0xF1 || Data[1] != 0xF1 {
		return ErrorProtocol
	}
	o.M1Flag = binary.BigEndian.Uint16(Data[0:2])
	o.M1Leng = binary.BigEndian.Uint16(Data[2:4])
	o.M1Cmd = Data[4]
	o.M1Crc = binary.BigEndian.Uint16(Data[o.M1Leng+5 : o.M1Leng+7])
	//校验CRC1
	crc := CRC16(Data[0 : o.M1Leng+5])
	if o.M1Crc != crc {
		return ErrorInvalidCrc1
	}
	return ErrorProtocol
}

type PackGetPidAck struct {
	M1Flag uint16 //固定为F1F1
	M1Leng uint16 //包体1长度
	M1Cmd  uint8  //1字节
	Body1  PidFreq
	M1Crc  uint16 //整包CRC
}

func (o *PackGetPidAck) SetData(pid uint16, freq byte) {
	o.Body1.PID = pid
	o.Body1.Frequency = freq
}

func (o *PackGetPidAck) EnCode() (*bytebufferpool.ByteBuffer, error) {
	bytebuf, err := o.Body1.EnCode()
	defer func() {
		if bytebuf != nil {
			bytebufferpool.Put(bytebuf)
		}
	}()
	if err != nil {
		return nil, err
	}
	buff := bytebufferpool.Get()
	buff.Write([]byte{0xF1, 0xF1}) //M1Flag uint16  //固定为F1F1
	tmp := make([]byte, 2)
	binary.BigEndian.PutUint16(tmp, uint16(bytebuf.Len()))
	buff.Write(tmp)              //M1Leng   uint16  //包体1长度
	buff.WriteByte(CmdGetPidAck) //M1Cmd      uint8   //1字节
	buff.Write(bytebuf.B)        //包体1

	//crc1
	crc16 := CRC16(buff.B)
	tmp2 := make([]byte, 2)
	binary.BigEndian.PutUint16(tmp2, crc16)
	buff.Write(tmp2) //外层CRC16
	return buff, nil
}

func (o *PackGetPidAck) DeCode(Data []byte) error {
	if len(Data) < 7 {
		return ErrorProtocol
	}
	if Data[0] != 0xF1 || Data[1] != 0xF1 {
		return ErrorProtocol
	}
	o.M1Flag = binary.BigEndian.Uint16(Data[0:2])
	o.M1Leng = binary.BigEndian.Uint16(Data[2:4])
	o.M1Cmd = Data[4]
	o.M1Crc = binary.BigEndian.Uint16(Data[o.M1Leng+5 : o.M1Leng+7])
	//校验CRC1
	crc := CRC16(Data[0 : o.M1Leng+5])
	if o.M1Crc != crc {
		return ErrorInvalidCrc1
	}
	if o.M1Leng > 0 {
		return o.Body1.DeCode(Data[5 : o.M1Leng+5])
	}
	return ErrorProtocol
}
