package pgproto3

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

	"github.com/jackc/pgx/chunkreader"
)

type Backend struct {
	cr *chunkreader.ChunkReader
	w  io.Writer

	// Frontend message flyweights
	bind            Bind
	describe        Describe
	execute         Execute
	parse           Parse
	passwordMessage PasswordMessage
	query           Query
	sync            Sync
	terminate       Terminate
}

func NewBackend(r io.Reader, w io.Writer) (*Backend, error) {
	cr := chunkreader.NewChunkReader(r)
	return &Backend{cr: cr, w: w}, nil
}

func (b *Backend) Send(msg BackendMessage) error {
	return errors.New("not implemented")
}

func (b *Backend) Receive() (FrontendMessage, error) {
	header, err := b.cr.Next(5)
	if err != nil {
		return nil, err
	}

	msgType := header[0]
	bodyLen := int(binary.BigEndian.Uint32(header[1:])) - 4

	var msg FrontendMessage
	switch msgType {
	case 'B':
		msg = &b.bind
	case 'D':
		msg = &b.describe
	case 'E':
		msg = &b.execute
	case 'P':
		msg = &b.parse
	case 'p':
		msg = &b.passwordMessage
	case 'Q':
		msg = &b.query
	case 'S':
		msg = &b.sync
	case 'X':
		msg = &b.terminate
	default:
		return nil, fmt.Errorf("unknown message type: %c", msgType)
	}

	msgBody, err := b.cr.Next(bodyLen)
	if err != nil {
		return nil, err
	}

	err = msg.Decode(msgBody)
	return msg, err
}