package rpc

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

const (
	FuncPing     uint8 = 0x01
	FuncRequest        = 0x02
	FuncResponse       = 0x03
)

var (
	feature           = []byte{82, 80, 67} //RPC数据包
	errInvalidPackage = errors.New("invalid package")
)

type Frame struct {
	Feature  []byte //特征码 RPC
	Func     uint8
	Sequence uint16
	Length   uint16
	Data     []byte
}

func readFrame(r io.Reader) (frame *Frame, err error) {
	var (
		n int
	)
	frame = &Frame{Feature: make([]byte, 3)}
	if _, err = io.ReadFull(r, frame.Feature); err != nil {
		return
	}
	if !bytes.Equal(frame.Feature, feature) {
		err = errInvalidPackage
		return
	}
	if err = binary.Read(r, binary.LittleEndian, &frame.Func); err != nil {
		return
	}
	if err = binary.Read(r, binary.LittleEndian, &frame.Sequence); err != nil {
		return
	}
	if err = binary.Read(r, binary.LittleEndian, &frame.Length); err != nil {
		return
	}
	frame.Data = make([]byte, frame.Length)
	if n, err = io.ReadFull(r, frame.Data); err == nil {
		if n < int(frame.Length) {
			err = io.ErrShortBuffer
		}
	}
	return
}

func writeFrame(w io.Writer, frame *Frame) (err error) {
	var (
		n int
	)
	if frame.Length == 0 {
		frame.Length = uint16(len(frame.Data))
	}
	if _, err = w.Write(feature); err != nil {
		return
	}
	if err = binary.Write(w, binary.LittleEndian, frame.Func); err != nil {
		return
	}
	if err = binary.Write(w, binary.LittleEndian, frame.Sequence); err != nil {
		return
	}
	if err = binary.Write(w, binary.LittleEndian, frame.Length); err != nil {
		return
	}
	if n, err = w.Write(frame.Data); err == nil {
		if n < int(frame.Length) {
			err = io.ErrShortWrite
		}
	}
	return
}
