package codec

import (
	"encoding/binary"
	"errors"
	"io"

	"github.com/panjf2000/gnet/v2"
)

var ErrIncompletePacket = errors.New("incomplete packet")

// TomeeSocketCodec 协议格式:
//
// * 0           4
// * +-----------+
// * |  body len  |
// * +-----------+
// * |           |
// * +           +
// * | body bytes|
// * +           +
// * |  ... ...  |
// * +-----------+
type TomeeSocketCodec struct{}

var _ SocketCodec = (*TomeeSocketCodec)(nil)

func NewTomeeSocketCodec() *TomeeSocketCodec {
	return &TomeeSocketCodec{}

}

func (codec TomeeSocketCodec) Encode(buf []byte) ([]byte, error) {
	bodyLen := len(buf)
	data := make([]byte, 4+bodyLen)

	// 写入4字节的包长度
	binary.BigEndian.PutUint32(data[:4], uint32(bodyLen))
	// 写入包体
	copy(data[4:], buf)

	return data, nil
}

func (codec TomeeSocketCodec) Decode(c gnet.Conn) ([]byte, error) {

	//	handle(c)
	// 先读取4字节的包长度
	lenBuf, err := c.Peek(4)
	if err != nil {
		if errors.Is(err, io.ErrShortBuffer) {
			return nil, ErrIncompletePacket
		}
		return nil, err
	}

	bodyLen := binary.BigEndian.Uint32(lenBuf)
	totalLen := 4 + int(bodyLen)

	// 检查整个包是否完整
	buf, err := c.Peek(int(bodyLen))
	if err != nil {
		if errors.Is(err, io.ErrShortBuffer) {
			return nil, ErrIncompletePacket
		}
		return nil, err
	}

	// 提取包体
	body := make([]byte, bodyLen)
	copy(body, buf)

	// 从缓冲区中丢弃已读取的数据
	_, _ = c.Discard(totalLen)

	return body, nil
}
