// Code generated by meshRPC. DO NOT EDIT.
// All changes must be done in custom client that should either embed or wrap this.

package greeter

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"

	"github.com/astranet/httpserve"
	"github.com/pkg/errors"
)

type ServiceClient interface {
	Service
}

type ServiceClientOptions struct {
}

func checkServiceClientOptions(opt *ServiceClientOptions) *ServiceClientOptions {
	if opt == nil {
		opt = &ServiceClientOptions{}
	}
	return opt
}

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

func NewServiceClient(
	httpClient HTTPClient,
	opt *ServiceClientOptions,
) ServiceClient {
	return &rpcClient{
		opt:        checkServiceClientOptions(opt),
		httpClient: httpClient,
	}
}

type rpcClient struct {
	opt        *ServiceClientOptions
	httpClient HTTPClient
}

func (_client *rpcClient) Greet(name string) (message string, _err error) {
	// TODO: Report Stats + Timing

	_req := &GreetRequest{
		Name: name,
	}
	var _resp *GreetResponse
	var _respBody []byte
	_respBody, _err = _client.do(_client.newJsonReq("POST", "Greet", _req))
	if _err != nil {
		return
	} else if _err = httpserve.UnmarshalJSONValue(_respBody, &_resp); _err != nil {
		return
	}
	message = _resp.Message
	return
}

func (_client *rpcClient) SendPostcard(card *Postcard) (_err error) {
	// TODO: Report Stats + Timing

	_req := &SendPostcardRequest{
		Card: card,
	}
	var _resp *SendPostcardResponse
	var _respBody []byte
	_respBody, _err = _client.do(_client.newJsonReq("POST", "SendPostcard", _req))
	if _err != nil {
		return
	} else if _err = httpserve.UnmarshalJSONValue(_respBody, &_resp); _err != nil {
		return
	}
	return
}

func (_client *rpcClient) do(req *http.Request) ([]byte, error) {
	resp, err := _client.httpClient.Do(req)
	if err != nil {
		err = errors.Errorf("rpcClient: %v", err)
		return nil, err
	}
	respBody, _ := ioutil.ReadAll(resp.Body)
	_ = resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		if len(respBody) > 0 {
			err := errors.Errorf("service error %d: %s", resp.StatusCode, string(respBody))
			return nil, err
		}
		err := errors.Errorf("service error %d: %s", resp.StatusCode, resp.Status)
		return nil, err
	}
	return respBody, nil
}

func (_client *rpcClient) newJsonReq(method string, fnName string, v interface{}) *http.Request {
	data, _ := json.Marshal(v)
	req, _ := http.NewRequest(method, fnName, bytes.NewReader(data))
	return req
}

func (_client *rpcClient) checkJsonRespErr(resp []byte) error {
	var e ErrorResponse
	_ = json.Unmarshal(resp, &e)
	if len(e.Error) == 0 {
		return nil
	}
	return errors.New(e.Error)
}
