package connection

import (
	"fmt"
	"io"

	"github.com/lucas-clemente/quic-go"
	"github.com/lucas-clemente/quic-go/quicvarint"
)

type FrameReadStreamImpl struct {
	stream quic.ReceiveStream
}

func (f *FrameReadStreamImpl) Read(buf []byte) (int, error) {
	return f.stream.Read(buf)
}

// CancelRead - function for cancel stream reading. This is necessary in case the data read is enough to make a decision
func (f *FrameReadStreamImpl) CancelRead(errCode uint64) {
	f.stream.CancelRead(quic.StreamErrorCode(errCode))
}

func (f *FrameStreamImpl) Read(buf []byte) (int, error) {
	return f.stream.Read(buf)
}

// CancelRead - function for cancel stream reading. This is necessary in case the data read is enough to make a decision
func (f *FrameStreamImpl) CancelRead(errCode uint64) {
	f.stream.CancelRead(quic.StreamErrorCode(errCode))
}

func readHeader(str FrameReadStream) (*FrameHeader, error) {
	br := &byteReaderImpl{str}

	t, err := quicvarint.Read(br) // frame type
	if err != nil {
		str.CancelRead(AcceptReadFrameTypeError)
		return nil, err
	}
	hl, err := quicvarint.Read(br) // header length
	if err != nil {
		str.CancelRead(AcceptReadHeaderLengthError)
		return nil, err
	}
	bl, err := quicvarint.Read(br) // body length
	if err != nil {
		str.CancelRead(AcceptReadHeaderLengthError)
		return nil, err
	}

	if hl > MaxHeaderLength {
		str.CancelRead(AcceptMaxHeaderLengthReachedError)
		return nil, fmt.Errorf("Error! Header length greater than max header length")
	}

	header := &FrameHeader{
		BodyLength: bl,
	}

	switch t {
	case SystemFrameType, RequestFrameType, ResponseFrameType, EventFrameType:
		header.Type = FrameType(t)
	default:
		// Unknown type
		str.CancelRead(AcceptUnknownFrameTypeError)
		return nil, fmt.Errorf("Unknown frame type")
	}

	buf := make([]byte, hl)

	_, err = io.ReadFull(str, buf)
	if err != nil {
		str.CancelRead(AcceptReadHeaderError)
		return nil, err
	}

	header.Header = buf
	return header, nil
}
