/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package whisk

import (
	"bytes"
	"crypto/tls"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/apache/incubator-openwhisk-client-go/wski18n"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"reflect"
	"regexp"
	"runtime"
	"strings"
	"time"
)

const (
	AuthRequired                   = true
	NoAuth                         = false
	IncludeNamespaceInUrl          = true
	DoNotIncludeNamespaceInUrl     = false
	AppendOpenWhiskPathPrefix      = true
	DoNotAppendOpenWhiskPathPrefix = false
	EncodeBodyAsJson               = "json"
	EncodeBodyAsFormData           = "formdata"
	ProcessTimeOut                 = true
	DoNotProcessTimeOut            = false
	ExitWithErrorOnTimeout         = true
	ExitWithSuccessOnTimeout       = false
	DEFAULT_HTTP_TIMEOUT           = 30
)

type ClientInterface interface {
	NewRequestUrl(method string, urlRelResource *url.URL, body interface{}, includeNamespaceInUrl bool, appendOpenWhiskPath bool, encodeBodyAs string, useAuthentication bool) (*http.Request, error)
	NewRequest(method, urlStr string, body interface{}, includeNamespaceInUrl bool) (*http.Request, error)
	Do(req *http.Request, v interface{}, ExitWithErrorOnTimeout bool, secretToObfuscate ...ObfuscateSet) (*http.Response, error)
}

type Client struct {
	client *http.Client
	*Config
	Transport *http.Transport

	Sdks        *SdkService
	Triggers    *TriggerService
	Actions     *ActionService
	Rules       *RuleService
	Activations *ActivationService
	Packages    *PackageService
	Namespaces  *NamespaceService
	Info        *InfoService
	Apis        *ApiService
}

type Config struct {
	Namespace         string // NOTE :: Default is "_"
	Cert              string
	Key               string
	AuthToken         string
	Host              string
	BaseURL           *url.URL // NOTE :: Default is "openwhisk.ng.bluemix.net"
	Version           string
	Verbose           bool
	Debug             bool // For detailed tracing
	Insecure          bool
	UserAgent         string
	ApigwAccessToken  string
	AdditionalHeaders http.Header
}

type ObfuscateSet struct {
	Regex       string
	Replacement string
}

var DefaultObfuscateArr = []ObfuscateSet{
	{
		Regex:       "\"[Pp]assword\":\\s*\".*\"",
		Replacement: `"password": "******"`,
	},
}

func NewClient(httpClient *http.Client, config_input *Config) (*Client, error) {

	var config *Config
	if config_input == nil {
		defaultConfig, err := GetDefaultConfig()
		if err != nil {
			return nil, err
		} else {
			config = defaultConfig
		}
	} else {
		config = config_input
	}

	if httpClient == nil {
		httpClient = &http.Client{
			Timeout: time.Second * DEFAULT_HTTP_TIMEOUT,
		}
	}

	var err error
	var errStr = ""
	if len(config.Host) == 0 {
		errStr = wski18n.T("Unable to create request URL, because OpenWhisk API host is missing")
	} else if config.BaseURL == nil {
		config.BaseURL, err = GetUrlBase(config.Host)
		if err != nil {
			Debug(DbgError, "Unable to create request URL, because the api host %s is invalid\n", config.Host, err)
			errStr = wski18n.T("Unable to create request URL, because the api host '{{.host}}' is invalid: {{.err}}",
				map[string]interface{}{"host": config.Host, "err": err})
		}
	}

	if len(errStr) != 0 {
		werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
		return nil, werr
	}

	if len(config.Namespace) == 0 {
		config.Namespace = "_"
	}

	if len(config.Version) == 0 {
		config.Version = "v1"
	}

	if len(config.UserAgent) == 0 {
		config.UserAgent = "OpenWhisk-Go-Client " + runtime.GOOS + " " + runtime.GOARCH
	}

	c := &Client{
		client: httpClient,
		Config: config,
	}

	c.Sdks = &SdkService{client: c}
	c.Triggers = &TriggerService{client: c}
	c.Actions = &ActionService{client: c}
	c.Rules = &RuleService{client: c}
	c.Activations = &ActivationService{client: c}
	c.Packages = &PackageService{client: c}
	c.Namespaces = &NamespaceService{client: c}
	c.Info = &InfoService{client: c}
	c.Apis = &ApiService{client: c}

	return c, nil
}

func (c *Client) LoadX509KeyPair() error {
	tlsConfig := &tls.Config{
		InsecureSkipVerify: c.Config.Insecure,
	}

	if c.Config.Cert != "" && c.Config.Key != "" {
		if cert, err := ReadX509KeyPair(c.Config.Cert, c.Config.Key); err == nil {
			tlsConfig.Certificates = []tls.Certificate{cert}
		} else {
			errStr := wski18n.T("Unable to load the X509 key pair due to the following reason: {{.err}}",
				map[string]interface{}{"err": err})
			werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
			return werr
		}
	} else if !c.Config.Insecure {
		if c.Config.Cert == "" {
			warningStr := "The Cert file is not configured. Please configure the missing Cert file, if there is a security issue accessing the service.\n"
			Debug(DbgWarn, warningStr)
			if c.Config.Key != "" {
				errStr := wski18n.T("The Cert file is not configured. Please configure the missing Cert file.\n")
				werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
				return werr
			}
		}
		if c.Config.Key == "" {
			warningStr := "The Key file is not configured. Please configure the missing Key file, if there is a security issue accessing the service.\n"
			Debug(DbgWarn, warningStr)
			if c.Config.Cert != "" {
				errStr := wski18n.T("The Key file is not configured. Please configure the missing Key file.\n")
				werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
				return werr
			}
		}
	}

	// Use the defaultTransport as the transport basis to maintain proxy support
	// Make a copy of the defaultTransport so that the original defaultTransport is left alone
	defaultTransportCopy := *(http.DefaultTransport.(*http.Transport))
	defaultTransportCopy.TLSClientConfig = tlsConfig
	c.client.Transport = &defaultTransportCopy

	return nil
}

var ReadX509KeyPair = func(certFile, keyFile string) (tls.Certificate, error) {
	return tls.LoadX509KeyPair(certFile, keyFile)
}

///////////////////////////////
// Request/Utility Functions //
///////////////////////////////

func (c *Client) NewRequest(method, urlStr string, body interface{}, includeNamespaceInUrl bool) (*http.Request, error) {
	werr := c.LoadX509KeyPair()
	if werr != nil {
		return nil, werr
	}

	if includeNamespaceInUrl {
		if c.Config.Namespace != "" {
			urlStr = fmt.Sprintf("%s/namespaces/%s/%s", c.Config.Version, c.Config.Namespace, urlStr)
		} else {
			urlStr = fmt.Sprintf("%s/namespaces", c.Config.Version)
		}
	} else {
		urlStr = fmt.Sprintf("%s/%s", c.Config.Version, urlStr)
	}

	urlStr = fmt.Sprintf("%s/%s", c.BaseURL.String(), urlStr)
	u, err := url.Parse(urlStr)
	if err != nil {
		Debug(DbgError, "url.Parse(%s) error: %s\n", urlStr, err)
		errStr := wski18n.T("Invalid request URL '{{.url}}': {{.err}}",
			map[string]interface{}{"url": urlStr, "err": err})
		werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
		return nil, werr
	}

	var buf io.ReadWriter
	if body != nil {
		buf = new(bytes.Buffer)
		encoder := json.NewEncoder(buf)
		encoder.SetEscapeHTML(false)
		err := encoder.Encode(body)

		if err != nil {
			Debug(DbgError, "json.Encode(%#v) error: %s\n", body, err)
			errStr := wski18n.T("Error encoding request body: {{.err}}", map[string]interface{}{"err": err})
			werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
			return nil, werr
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		Debug(DbgError, "http.NewRequest(%v, %s, buf) error: %s\n", method, u.String(), err)
		errStr := wski18n.T("Error initializing request: {{.err}}", map[string]interface{}{"err": err})
		werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
		return nil, werr
	}
	if req.Body != nil {
		req.Header.Add("Content-Type", "application/json")
	}

	err = c.addAuthHeader(req, AuthRequired)
	if err != nil {
		Debug(DbgError, "addAuthHeader() error: %s\n", err)
		errStr := wski18n.T("Unable to add the HTTP authentication header: {{.err}}",
			map[string]interface{}{"err": err})
		werr := MakeWskErrorFromWskError(errors.New(errStr), err, EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
		return nil, werr
	}

	req.Header.Add("User-Agent", c.Config.UserAgent)

	for key := range c.Config.AdditionalHeaders {
		req.Header.Add(key, c.Config.AdditionalHeaders.Get(key))
	}

	return req, nil
}

func (c *Client) addAuthHeader(req *http.Request, authRequired bool) error {
	if c.Config.AuthToken != "" {
		encodedAuthToken := base64.StdEncoding.EncodeToString([]byte(c.Config.AuthToken))
		req.Header.Add("Authorization", fmt.Sprintf("Basic %s", encodedAuthToken))
		Debug(DbgInfo, "Adding basic auth header; using authkey\n")
	} else {
		if authRequired {
			Debug(DbgError, "The required authorization key is not configured - neither set as a property nor set via the --auth CLI argument\n")
			errStr := wski18n.T("Authorization key is not configured (--auth is required)")
			werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_USAGE, DISPLAY_MSG, DISPLAY_USAGE)
			return werr
		}
	}
	return nil
}

// bodyTruncator limits the size of Req/Resp Body for --verbose ONLY.
// It returns truncated Req/Resp Body, reloaded io.ReadCloser and any errors.
func BodyTruncator(body io.ReadCloser) (string, io.ReadCloser, error) {
	limit := 1000 // 1000 byte limit, anything over is truncated

	data, err := ioutil.ReadAll(body)
	if err != nil {
		Verbose("ioutil.ReadAll(req.Body) error: %s\n", err)
		werr := MakeWskError(err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG, NO_DISPLAY_USAGE)
		return "", body, werr
	}

	reload := ioutil.NopCloser(bytes.NewBuffer(data))

	if len(data) > limit {
		Verbose("Body exceeds %d bytes and will be truncated\n", limit)
		newData := string(data)[:limit] + "..."
		return string(newData), reload, nil
	}

	return string(data), reload, nil
}

// Do sends an API request and returns the API response.  The API response is
// JSON decoded and stored in the value pointed to by v, or returned as an
// error if an API error has occurred.  If v implements the io.Writer
// interface, the raw response body will be written to v, without attempting to
// first decode it.
func (c *Client) Do(req *http.Request, v interface{}, ExitWithErrorOnTimeout bool, secretToObfuscate ...ObfuscateSet) (*http.Response, error) {
	var err error
	var data []byte
	secrets := append(DefaultObfuscateArr, secretToObfuscate...)

	req, err = PrintRequestInfo(req, secrets...)
	//Putting this based on previous code
	if err != nil {
		return nil, err
	}

	// Issue the request to the Whisk server endpoint
	resp, err := c.client.Do(req)
	if err != nil {
		Debug(DbgError, "HTTP Do() [req %s] error: %s\n", req.URL.String(), err)
		werr := MakeWskError(err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG, NO_DISPLAY_USAGE)
		return nil, werr
	}

	resp, data, err = PrintResponseInfo(resp, secrets...)
	if err != nil {
		return resp, err
	}

	// With the HTTP response status code and the HTTP body contents,
	// the possible response scenarios are:
	//
	// 0. HTTP Success + Body indicating a whisk failure result
	// 1. HTTP Success + Valid body matching request expectations
	// 2. HTTP Success + No body expected
	// 3. HTTP Success + Body does NOT match request expectations
	// 4. HTTP Failure + No body
	// 5. HTTP Failure + Body matching error format expectation
	// 6. HTTP Failure + Body NOT matching error format expectation

	// Handle 4. HTTP Failure + No body
	// If this happens, just return no data and an error
	if !IsHttpRespSuccess(resp) && data == nil {
		Debug(DbgError, "HTTP failure %d + no body\n", resp.StatusCode)
		werr := MakeWskError(errors.New(wski18n.T("Command failed due to an HTTP failure")), resp.StatusCode-256,
			DISPLAY_MSG, NO_DISPLAY_USAGE)
		return resp, werr
	}

	// Handle 5. HTTP Failure + Body matching error format expectation, or body matching a whisk.error() response
	// Handle 6. HTTP Failure + Body NOT matching error format expectation
	if !IsHttpRespSuccess(resp) && data != nil {
		return parseErrorResponse(resp, data, v)
	}

	// Handle 0. HTTP Success + Body indicating a whisk failure result
	//   NOTE: Need to ignore activation records send in response to 'wsk get activation NNN` as
	//         these will report the same original error giving the appearance that the command failed.
	//         Need to ignore `wsk action invoke NNN --result` too, otherwise action whose result is sth likes
	//         '{"response": {"key": "value"}}' will return an error to such command.
	if IsHttpRespSuccess(resp) && // HTTP Status == 200
		data != nil && // HTTP response body exists
		v != nil &&
		!strings.Contains(reflect.TypeOf(v).String(), "Activation") && // Request is not `wsk activation get`
		!(req.URL.Query().Get("result") == "true") && // Request is not `wsk action invoke NNN --result`
		!IsResponseResultSuccess(data) { // HTTP response body has Whisk error result
		Debug(DbgInfo, "Got successful HTTP; but activation response reports an error\n")
		return parseErrorResponse(resp, data, v)
	}

	// Handle 2. HTTP Success + No body expected
	if IsHttpRespSuccess(resp) && v == nil {
		Debug(DbgInfo, "No interface provided; no HTTP response body expected\n")
		return resp, nil
	}

	// Handle 1. HTTP Success + Valid body matching request expectations
	// Handle 3. HTTP Success + Body does NOT match request expectations
	if IsHttpRespSuccess(resp) && v != nil {

		// If a timeout occurs, 202 HTTP status code is returned, and the caller wishes to handle such an event, return
		// an error corresponding with the timeout
		if ExitWithErrorOnTimeout && resp.StatusCode == EXIT_CODE_TIMED_OUT {
			errMsg := wski18n.T("Request accepted, but processing not completed yet.")
			err = MakeWskError(errors.New(errMsg), EXIT_CODE_TIMED_OUT, NO_DISPLAY_MSG, NO_DISPLAY_USAGE,
				NO_MSG_DISPLAYED, NO_DISPLAY_PREFIX, NO_APPLICATION_ERR, TIMED_OUT)
		}

		return parseSuccessResponse(resp, data, v), err
	}

	// We should never get here, but just in case return failure to keep the compiler happy
	werr := MakeWskError(errors.New(wski18n.T("Command failed due to an internal failure")), EXIT_CODE_ERR_GENERAL,
		DISPLAY_MSG, NO_DISPLAY_USAGE)
	return resp, werr
}

func PrintRequestInfo(req *http.Request, secretToObfuscate ...ObfuscateSet) (*http.Request, error) {
	var truncatedBody string
	var err error
	if IsVerbose() {
		fmt.Println("REQUEST:")
		fmt.Printf("[%s]\t%s\n", req.Method, req.URL)

		if len(req.Header) > 0 {
			fmt.Println("Req Headers")
			PrintJSON(req.Header)
		}

		if req.Body != nil {
			fmt.Println("Req Body")
			// Since we're emptying out the reader, which is the req.Body, we have to reset it,
			// but create some copies for our debug messages.
			buffer, _ := ioutil.ReadAll(req.Body)
			obfuscatedRequest := ObfuscateText(string(buffer), secretToObfuscate)
			req.Body = ioutil.NopCloser(bytes.NewBuffer(buffer))

			if !IsDebug() {
				if truncatedBody, req.Body, err = BodyTruncator(ioutil.NopCloser(bytes.NewBuffer(buffer))); err != nil {
					return nil, err
				}
				fmt.Println(ObfuscateText(truncatedBody, secretToObfuscate))
			} else {
				fmt.Println(obfuscatedRequest)
			}
			Debug(DbgInfo, "Req Body (ASCII quoted string):\n%+q\n", obfuscatedRequest)
		}
	}
	return req, nil
}

func PrintResponseInfo(resp *http.Response, secretToObfuscate ...ObfuscateSet) (*http.Response, []byte, error) {
	var truncatedBody string
	// Don't "defer resp.Body.Close()" here because the body is reloaded to allow caller to
	// do custom body parsing, such as handling per-route error responses.
	Verbose("RESPONSE:")
	Verbose("Got response with code %d\n", resp.StatusCode)

	if IsVerbose() && len(resp.Header) > 0 {
		fmt.Println("Resp Headers")
		PrintJSON(resp.Header)
	}

	// Read the response body
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		Debug(DbgError, "ioutil.ReadAll(resp.Body) error: %s\n", err)
		werr := MakeWskError(err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG, NO_DISPLAY_USAGE)
		resp.Body = ioutil.NopCloser(bytes.NewBuffer(data))
		return resp, data, werr
	}

	// Reload the response body to allow caller access to the body; otherwise,
	// the caller will have any empty body to read
	resp.Body = ioutil.NopCloser(bytes.NewBuffer(data))

	Verbose("Response body size is %d bytes\n", len(data))

	if !IsDebug() {
		if truncatedBody, resp.Body, err = BodyTruncator(ioutil.NopCloser(bytes.NewBuffer(data))); err != nil {
			return nil, data, err
		}
		Verbose("Response body received:\n%s\n", ObfuscateText(truncatedBody, secretToObfuscate))
	} else {
		obfuscatedResponse := ObfuscateText(string(data), secretToObfuscate)
		Verbose("Response body received:\n%s\n", obfuscatedResponse)
		Debug(DbgInfo, "Response body received (ASCII quoted string):\n%+q\n", obfuscatedResponse)
	}
	return resp, data, err
}

func ObfuscateText(text string, replacements []ObfuscateSet) string {
	obfuscated := text
	for _, oSet := range replacements {
		r, _ := regexp.Compile(oSet.Regex)
		obfuscated = r.ReplaceAllString(obfuscated, oSet.Replacement)
	}
	return obfuscated
}

func parseErrorResponse(resp *http.Response, data []byte, v interface{}) (*http.Response, error) {
	Debug(DbgInfo, "HTTP failure %d + body\n", resp.StatusCode)

	// Determine if an application error was received (#5)
	buf := bytes.NewBuffer(data)
	d := json.NewDecoder(buf)
	d.UseNumber()

	errorResponse := &ErrorResponse{Response: resp}
	err := d.Decode(&errorResponse)

	// Determine if error is an application error or an error generated by API
	if err == nil {
		if errorResponse.Code == nil /*&& errorResponse.ErrMsg != nil */ && resp.StatusCode == 502 {
			return parseApplicationError(resp, data, v)
		} else if errorResponse.Code != nil && errorResponse.ErrMsg != nil {
			Debug(DbgInfo, "HTTP failure %d; server error %s\n", resp.StatusCode, errorResponse)
			werr := MakeWskError(errorResponse, resp.StatusCode-256, DISPLAY_MSG, NO_DISPLAY_USAGE)
			return resp, werr
		}
	}

	// Body contents are unknown (#6)
	Debug(DbgError, "HTTP response with unexpected body failed due to contents parsing error: '%v'\n", err)
	errMsg := wski18n.T("The connection failed, or timed out. (HTTP status code {{.code}})",
		map[string]interface{}{"code": resp.StatusCode})
	whiskErr := MakeWskError(errors.New(errMsg), resp.StatusCode-256, DISPLAY_MSG, NO_DISPLAY_USAGE)
	return resp, whiskErr
}

func parseApplicationError(resp *http.Response, data []byte, v interface{}) (*http.Response, error) {
	Debug(DbgInfo, "Parsing application error\n")

	whiskErrorResponse := &WhiskErrorResponse{}
	err := json.Unmarshal(data, whiskErrorResponse)

	// Handle application errors that occur when --result option is false (#5)
	if err == nil && whiskErrorResponse != nil && whiskErrorResponse.Response != nil && whiskErrorResponse.Response.Status != nil {
		Debug(DbgInfo, "Detected response status `%s` that a whisk.error(\"%#v\") was returned\n",
			*whiskErrorResponse.Response.Status, *whiskErrorResponse.Response.Result)
		errMsg := wski18n.T("The following application error was received: {{.err}}",
			map[string]interface{}{"err": *whiskErrorResponse.Response.Result})
		whiskErr := MakeWskError(errors.New(errMsg), resp.StatusCode-256, NO_DISPLAY_MSG, NO_DISPLAY_USAGE,
			NO_MSG_DISPLAYED, DISPLAY_PREFIX, APPLICATION_ERR)
		return parseSuccessResponse(resp, data, v), whiskErr
	}

	appErrResult := &AppErrorResult{}
	err = json.Unmarshal(data, appErrResult)

	// Handle application errors that occur with blocking invocations when --result option is true (#5)
	if err == nil && appErrResult.Error != nil {
		Debug(DbgInfo, "Error code is null, blocking with result invocation error has occured\n")
		errMsg := fmt.Sprintf("%v", *appErrResult.Error)
		Debug(DbgInfo, "Application error received: %s\n", errMsg)

		whiskErr := MakeWskError(errors.New(errMsg), resp.StatusCode-256, NO_DISPLAY_MSG, NO_DISPLAY_USAGE,
			NO_MSG_DISPLAYED, DISPLAY_PREFIX, APPLICATION_ERR)
		return parseSuccessResponse(resp, data, v), whiskErr
	}

	// Body contents are unknown (#6)
	Debug(DbgError, "HTTP response with unexpected body failed due to contents parsing error: '%v'\n", err)
	errMsg := wski18n.T("The connection failed, or timed out. (HTTP status code {{.code}})",
		map[string]interface{}{"code": resp.StatusCode})
	whiskErr := MakeWskError(errors.New(errMsg), resp.StatusCode-256, DISPLAY_MSG, NO_DISPLAY_USAGE)
	return resp, whiskErr
}

func parseSuccessResponse(resp *http.Response, data []byte, v interface{}) *http.Response {
	Debug(DbgInfo, "Parsing HTTP response into struct type: %s\n", reflect.TypeOf(v))

	dc := json.NewDecoder(strings.NewReader(string(data)))
	dc.UseNumber()
	err := dc.Decode(v)

	// If the decode was successful, return the response without error (#1). Otherwise, the decode did not work, so the
	// server response was unexpected (#3)
	if err == nil {
		Debug(DbgInfo, "Successful parse of HTTP response into struct type: %s\n", reflect.TypeOf(v))
		return resp
	} else {
		Debug(DbgWarn, "Unsuccessful parse of HTTP response into struct type: %s; parse error '%v'\n", reflect.TypeOf(v), err)
		Debug(DbgWarn, "Request was successful, so ignoring the following unexpected response body that could not be parsed: %s\n", data)
		return resp
	}
}

////////////
// Errors //
////////////

// For containing the server response body when an error message is returned
// Here's an example error response body with HTTP status code == 400
// {
//     "error": "namespace contains invalid characters",
//     "code": "1422870"
// }
type ErrorResponse struct {
	Response *http.Response // HTTP response that caused this error
	ErrMsg   *interface{}   `json:"error"` // error message string
	Code     *interface{}   `json:"code"`  // validation error code (tid)
}

type AppErrorResult struct {
	Error *interface{} `json:"error"`
}

type WhiskErrorResponse struct {
	Response *WhiskResponse `json:"response"`
}

type WhiskResponse struct {
	Result  *WhiskResult `json:"result"`
	Success bool         `json:"success"`
	Status  *interface{} `json:"status"`
}

type WhiskResult struct {
	//  Error   *WhiskError     `json:"error"`  // whisk.error(<string>) and whisk.reject({msg:<string>}) result in two different kinds of 'error' JSON objects
}

type WhiskError struct {
	Msg *string `json:"msg"`
}

func (r ErrorResponse) Error() string {
	return wski18n.T("{{.msg}} (code {{.code}})",
		map[string]interface{}{"msg": fmt.Sprintf("%v", *r.ErrMsg), "code": r.Code})
}

////////////////////////////
// Basic Client Functions //
////////////////////////////

func IsHttpRespSuccess(r *http.Response) bool {
	return r.StatusCode >= 200 && r.StatusCode <= 299
}

func IsResponseResultSuccess(data []byte) bool {
	errResp := new(WhiskErrorResponse)
	err := json.Unmarshal(data, &errResp)
	if err == nil && errResp.Response != nil {
		return errResp.Response.Success
	}
	Debug(DbgWarn, "IsResponseResultSuccess: failed to parse response result: %v\n", err)
	return true
}

//
// Create a HTTP request object using URL stored in url.URL object
// Arguments:
//   method         - HTTP verb (i.e. "GET", "PUT", etc)
//   urlRelResource - *url.URL structure representing the relative resource URL, including query params
//   body           - optional. Object whose contents will be JSON encoded and placed in HTTP request body
//   includeNamespaceInUrl - when true "/namespaces/NAMESPACE" is included in the final URL; otherwise not included.
//   appendOpenWhiskPath - when true, the OpenWhisk URL format is generated
//   encodeBodyAs   - specifies body encoding (json or form data)
//   useAuthentication - when true, the basic Authorization is included with the configured authkey as the value
func (c *Client) NewRequestUrl(
	method string,
	urlRelResource *url.URL,
	body interface{},
	includeNamespaceInUrl bool,
	appendOpenWhiskPath bool,
	encodeBodyAs string,
	useAuthentication bool) (*http.Request, error) {
	var requestUrl *url.URL
	var err error
	error := c.LoadX509KeyPair()
	if error != nil {
		return nil, error
	}

	if appendOpenWhiskPath {
		var urlVerNamespaceStr string
		var verPathEncoded = (&url.URL{Path: c.Config.Version}).String()

		if includeNamespaceInUrl {
			if c.Config.Namespace != "" {
				// Encode path parts before inserting them into the URI so that any '?' is correctly encoded
				// as part of the path and not the start of the query params
				verNamespaceEncoded := (&url.URL{Path: c.Config.Namespace}).String()
				urlVerNamespaceStr = fmt.Sprintf("%s/namespaces/%s", verPathEncoded, verNamespaceEncoded)
			} else {
				urlVerNamespaceStr = fmt.Sprintf("%s/namespaces", verPathEncoded)
			}
		} else {
			urlVerNamespaceStr = fmt.Sprintf("%s", verPathEncoded)
		}

		// Assemble the complete URL: base + version + [namespace] + resource_relative_path
		Debug(DbgInfo, "basepath: %s, version/namespace path: %s, resource path: %s\n", c.BaseURL.String(), urlVerNamespaceStr, urlRelResource.String())
		urlStr := fmt.Sprintf("%s/%s/%s", c.BaseURL.String(), urlVerNamespaceStr, urlRelResource.String())
		requestUrl, err = url.Parse(urlStr)
		if err != nil {
			Debug(DbgError, "url.Parse(%s) error: %s\n", urlStr, err)
			errStr := wski18n.T("Invalid request URL '{{.url}}': {{.err}}",
				map[string]interface{}{"url": urlStr, "err": err})
			werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
			return nil, werr
		}
	} else {
		Debug(DbgInfo, "basepath: %s, resource path: %s\n", c.BaseURL.String(), urlRelResource.String())
		urlStr := fmt.Sprintf("%s/%s", c.BaseURL.String(), urlRelResource.String())
		requestUrl, err = url.Parse(urlStr)
		if err != nil {
			Debug(DbgError, "url.Parse(%s) error: %s\n", urlStr, err)
			errStr := wski18n.T("Invalid request URL '{{.url}}': {{.err}}",
				map[string]interface{}{"url": urlStr, "err": err})
			werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
			return nil, werr
		}
	}

	var buf io.ReadWriter
	if body != nil {
		if encodeBodyAs == EncodeBodyAsJson {
			buf = new(bytes.Buffer)
			encoder := json.NewEncoder(buf)
			encoder.SetEscapeHTML(false)
			err := encoder.Encode(body)

			if err != nil {
				Debug(DbgError, "json.Encode(%#v) error: %s\n", body, err)
				errStr := wski18n.T("Error encoding request body: {{.err}}",
					map[string]interface{}{"err": err})
				werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
				return nil, werr
			}
		} else if encodeBodyAs == EncodeBodyAsFormData {
			if values, ok := body.(url.Values); ok {
				buf = bytes.NewBufferString(values.Encode())
			} else {
				Debug(DbgError, "Invalid form data body: %v\n", body)
				errStr := wski18n.T("Internal error.  Form data encoding failure")
				werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
				return nil, werr
			}
		} else {
			Debug(DbgError, "Invalid body encode type: %s\n", encodeBodyAs)
			errStr := wski18n.T("Internal error.  Invalid encoding type '{{.encodetype}}'",
				map[string]interface{}{"encodetype": encodeBodyAs})
			werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
			return nil, werr
		}
	}

	req, err := http.NewRequest(method, requestUrl.String(), buf)
	if err != nil {
		Debug(DbgError, "http.NewRequest(%v, %s, buf) error: %s\n", method, requestUrl.String(), err)
		errStr := wski18n.T("Error initializing request: {{.err}}", map[string]interface{}{"err": err})
		werr := MakeWskError(errors.New(errStr), EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
		return nil, werr
	}
	if req.Body != nil && encodeBodyAs == EncodeBodyAsJson {
		req.Header.Add("Content-Type", "application/json")
	}
	if req.Body != nil && encodeBodyAs == EncodeBodyAsFormData {
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	}

	if useAuthentication {
		err = c.addAuthHeader(req, AuthRequired)
		if err != nil {
			Debug(DbgError, "addAuthHeader() error: %s\n", err)
			errStr := wski18n.T("Unable to add the HTTP authentication header: {{.err}}",
				map[string]interface{}{"err": err})
			werr := MakeWskErrorFromWskError(errors.New(errStr), err, EXIT_CODE_ERR_GENERAL, DISPLAY_MSG, NO_DISPLAY_USAGE)
			return nil, werr
		}
	} else {
		Debug(DbgInfo, "No auth header required\n")
	}

	req.Header.Add("User-Agent", c.Config.UserAgent)

	for key := range c.Config.AdditionalHeaders {
		req.Header.Add(key, c.Config.AdditionalHeaders.Get(key))
	}

	return req, nil
}
