package client

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"strings"

	"code.secondbit.org/auth.hg"
)

var (
	ErrNilClient     = errors.New("nil client wrapper")
	ErrNilHTTPClient = errors.New("nil client")
)

type Client struct {
	client  *http.Client
	address string
}

func New(address string) *Client {
	address = strings.TrimRight(address, "/")
	return &Client{
		address: address,
		client:  &http.Client{},
	}
}

func (c *Client) do(method, url string, request interface{}) (auth.Response, error) {
	if c == nil {
		return auth.Response{}, ErrNilClient
	}
	if c.client == nil {
		return auth.Response{}, ErrNilHTTPClient
	}
	var response auth.Response
	if !strings.HasPrefix(url, "http") {
		url = strings.TrimLeft(url, "/")
		url = "/" + url
		url = c.address + url
	}
	var body io.Reader
	if request != nil {
		data, err := json.Marshal(request)
		if err != nil {
			return response, err
		}
		body = bytes.NewBuffer(data)
	}
	req, err := http.NewRequest(method, url, body)
	if err != nil {
		return response, err
	}
	resp, err := c.client.Do(req)
	if err != nil {
		return response, err
	}
	defer resp.Body.Close()
	switch resp.Header.Get("Content-Type") {
	case "application/json":
		dec := json.NewDecoder(resp.Body)
		err = dec.Decode(&response)
		if err != nil {
			return response, err
		}
	default:
		dec := json.NewDecoder(resp.Body)
		err = dec.Decode(&response)
		if err != nil {
			return response, err
		}
	}
	return response, nil
}

func (c *Client) Get(url string) (auth.Response, error) {
	return c.do("GET", url, nil)
}
