package connection

import (
	"context"
	"io"

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

type ConnectionSession struct {
	TransportSession SessionEvents

	TransportSyncReqReceiver SyncRequestReceiver

	context context.Context

	conn quic.Session
}

func (c *ConnectionSession) OpenStream(ctx context.Context, frHeader *FrameHeader) (FrameWriteStream, error) {
	str, err := NewOutgoingUniStream(ctx, c.conn)
	if err != nil {
		return nil, err
	}

	err = writeHeader(str, frHeader)
	if err != nil {
		return nil, err
	}

	return str, nil
}

func (c *ConnectionSession) SendSyncRequest(ctx context.Context, frHeader *FrameHeader, body []byte) (*FrameHeader, []byte, error) {
	str, err := NewOutgoingStream(ctx, c.conn)
	if err != nil {
		return nil, nil, err
	}
	defer str.Close()

	// Write request frame header and body
	err = writeHeader(str, frHeader)
	if err != nil {
		return nil, nil, err
	}

	_, err = str.Write(body)
	if err != nil {
		return nil, nil, err
	}

	// Read response header and body
	respHeader, err := readHeader(str)
	if err != nil {
		return nil, nil, err
	}
	buf := make([]byte, respHeader.BodyLength)
	_, err = io.ReadFull(str, buf)
	if err != nil {
		return nil, nil, err
	}

	return respHeader, buf, nil
}

func (c *ConnectionSession) GetContext() context.Context {
	return c.conn.Context()
}

func (c *ConnectionSession) Close() {
	c.conn.CloseWithError(quic.ApplicationErrorCode(quic.NoError), "connection closed")
}

func NewSession(conn quic.Session) *ConnectionSession {
	return &ConnectionSession{
		conn: conn,
	}
}
