
// Doer performs HTTP requests.
//
// The standard http.Client implements this interface.
type HTTPRequestDoer interface {
	Do(req *http.Request) (*http.Response, error)
}

// Client which conforms to the OpenAPI3 specification for this service.
type Client struct {
	// The endpoint of the server conforming to this interface, with scheme,
	// https://api.deepmap.com for example. This can contain a path relative
	// to the server, such as https://api.deepmap.com/dev-test, and all the
	// paths in the swagger spec will be appended to the server.
	Server string

    // Server + /api/v2/
	APIEndpoint string

	// Doer for performing requests, typically a *http.Client with any
	// customized settings, such as certificate chains.
	Client HTTPRequestDoer
}


// Creates a new Client, with reasonable defaults
func NewClient(server string, doer HTTPRequestDoer) (*Client, error) {
    // create a client with sane default values
    client := Client{
        Server: server,
        Client: doer,
    }
    // ensure the server URL always has a trailing slash
    if !strings.HasSuffix(client.Server, "/") {
        client.Server += "/"
    }
    // API endpoint
    client.APIEndpoint = client.Server + "api/v2/"

    // create httpClient, if not already present
    if client.Client == nil {
        client.Client = &http.Client{}
    }
    return &client, nil
}

func(e *Error) Error() error {
	return fmt.Errorf("%s: %s", string(e.Code), *e.Message)
}

func unmarshalJSONResponse(bodyBytes []byte, obj interface{}) error {
	if err := json.Unmarshal(bodyBytes, obj); err != nil {
		return err
	}
	return nil
}

func isJSON(rsp *http.Response) bool {
	ctype, _, _ := mime.ParseMediaType(rsp.Header.Get("Content-Type"))
    return  ctype == "application/json"
}

func decodeError(body []byte, rsp *http.Response) error {
	if isJSON(rsp) {
		var serverError  struct {
            Error
            V1Error *string `json:"error,omitempty"`
        }
		err := json.Unmarshal(body, &serverError)
		if err != nil {
			message := fmt.Sprintf("cannot decode error response: %v", err)
			serverError.Message = &message
		}
		if serverError.V1Error != nil {
            serverError.Message = serverError.V1Error
            serverError.Code = ErrorCodeInvalid
        }
		if serverError.Message == nil && serverError.Code == "" {
			serverError.Message = &rsp.Status
		}
		return serverError.Error.Error()
	} else {
		message := rsp.Status
		if len(body) > 0 {
			message = message + ": " + string(body)
		}
		return errors.New(message)
	}
}
