package client

import (
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
)

// httpClient allows http.Client to be mocked for tests
type httpClient interface {
	Do(*http.Request) (*http.Response, error)
}

// Generic REST restClient
type restClient struct {
	client  httpClient
	baseURL *url.URL
}

// do performs an HTTP request with this client and returns the response
func (c *restClient) do(method, uri string) (*http.Response, error) {
	rel, err := url.Parse(uri)
	if err != nil {
		return nil, err
	}

	url := c.baseURL.ResolveReference(rel)

	// Build the request
	req, err := http.NewRequest(method, url.String(), nil)
	if err != nil {
		return nil, err
	}

	// Send the request
	return c.client.Do(req)
}

// doGet performs an HTTP request with this client and marshalls the JSON response into v
func (c *restClient) doJSON(method string, uri string, v interface{}) error {
	resp, err := c.do(method, uri)
	if err != nil {
		return err
	}

	defer func() {
		_ = resp.Body.Close()
	}()
	if resp.StatusCode == http.StatusOK {
		if v == nil {
			return nil
		}
		// Decode response body
		return json.NewDecoder(resp.Body).Decode(v)
	}

	return fmt.Errorf("Unexpected HTTP response status %v: %s", resp.StatusCode, resp.Status)
}
