package jsonrpc2

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
)

type rwClient struct {
	enc *json.Encoder
	dec *json.Decoder
}

// NewReadWriterClient returns a Client which will use the given ReadWriter to
// perform requests.
func NewReadWriterClient(rw io.ReadWriter) Client {
	return rwClient{json.NewEncoder(rw), json.NewDecoder(rw)}
}

func (c rwClient) Call(
	ctx context.Context, rcv any, method string, args ...any,
) error {
	id, err := encodeRequest(ctx, c.enc, method, args)
	if err != nil {
		return fmt.Errorf("encoding request: %w", err)
	}

	resID, err := decodeResponse(c.dec, rcv)
	if errors.As(err, new(Error)) {
		return err
	} else if err != nil {
		return fmt.Errorf("decoding response: %w", err)
	} else if resID != id {
		return fmt.Errorf(
			"expected response with ID %q, got %q", id, resID,
		)
	}

	return nil
}