/*
 * 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"
	"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"
	}

	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)
	errorResponse := &ErrorResponse{Response: resp}
	err := json.Unmarshal(data, 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     *int64         `json:"code"`  // validation error code
}

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
}
