package protocol

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

type FrameType byte

const (
	TypeAttach FrameType = iota + 1
	TypeSnapshot
	TypeOutput
	TypeInput
	TypeResize
	TypeHop
	TypeInfo
	TypeInfoResp
	TypeKill
)

func ReadFrame(r io.Reader) (FrameType, []byte, error) {
	var h [5]byte
	if _, err := io.ReadFull(r, h[:]); err != nil {
		return 0, nil, err
	}
	n := binary.BigEndian.Uint32(h[1:5])
	if n > 16<<20 {
		return 0, nil, errors.New("frame too large")
	}
	p := make([]byte, n)
	if _, err := io.ReadFull(r, p); err != nil {
		return 0, nil, err
	}
	return FrameType(h[0]), p, nil
}

func WriteFrame(w io.Writer, t FrameType, payload []byte) error {
	_, err := w.Write(append(binary.BigEndian.AppendUint32([]byte{byte(t)}, uint32(len(payload))), payload...))
	return err
}

func EncodeSize(c, r int) []byte {
	return binary.BigEndian.AppendUint16(binary.BigEndian.AppendUint16(nil, uint16(c)), uint16(r))
}

func DecodeSize(b []byte) (int, int, error) {
	if len(b) < 4 {
		return 80, 24, errors.New("short size")
	}
	return int(binary.BigEndian.Uint16(b[:2])), int(binary.BigEndian.Uint16(b[2:4])), nil
}
