/*
 * 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"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"reflect"
	"regexp"
	"runtime"
	"strings"
	"time"

	"github.com/apache/openwhisk-client-go/wski18n"
)

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 TriggerServiceInterface interface {
	List(options *TriggerListOptions) ([]Trigger, *http.Response, error)
	Insert(trigger *Trigger, overwrite bool) (*Trigger, *http.Response, error)
	Get(triggerName string) (*Trigger, *http.Response, error)
	Delete(triggerName string) (*Trigger, *http.Response, error)
	Fire(triggerName string, payload interface{}) (*Trigger, *http.Response, error)
}

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

	Sdks        *SdkService
	Triggers    TriggerServiceInterface
	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
	ApigwTenantId     string
	AdditionalHeaders http.Header
}

type ObfuscateSet struct {
	Regex       string
	Replacement string
}

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

// NewClient creates a new whisk client with the provided http client and whisk configuration.
//
// A new http.Transport will be created when client cert or TLS insecure options are set.
// If one use custom tranport and want to keep it intact, please opt out TLS related fields
// in configInput and construct TLS conguration in the custom transport.
func NewClient(httpClient *http.Client, configInput *Config) (*Client, error) {

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

	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: %s\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}

	werr := c.LoadX509KeyPair()
	if werr != nil {
		return nil, werr
	}

	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
			}
		}
	}

	// Only replace the existing transport when a custom TLS configuration is needed
	if tlsConfig.InsecureSkipVerify || tlsConfig.Certificates != nil {
		if c.client.Transport != nil {
			warningStr := "The provided http.Transport is replaced to match the TLS configuration. Custom transport cannot coexist with nondefault TLS configuration"
			Debug(DbgWarn, warningStr)
		}
		// Use the defaultTransport as the transport basis to maintain proxy support
		c.client.Transport = &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			DialContext: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
				DualStack: true,
			}).DialContext,
			MaxIdleConns:          100,
			IdleConnTimeout:       90 * time.Second,
			TLSHandshakeTimeout:   10 * time.Second,
			ExpectContinueTimeout: 1 * time.Second,
			TLSClientConfig:       tlsConfig,
		}
	}

	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) {
	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 {
	// Allow for authorization override via Additional Headers
	authHeaderValue := c.Config.AdditionalHeaders.Get("Authorization")
	if authHeaderValue != "" {
		Debug(DbgInfo, "Using additional header authorization\n")
	} else 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)

		errStr := getApplicationErrorMessage(whiskErrorResponse.Response.Result)
		Debug(DbgInfo, "Application error received: %s\n", errStr)

		errMsg := wski18n.T("The following application error was received: {{.err}}",
			map[string]interface{}{"err": errStr})
		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 occurred\n")
		errStr := getApplicationErrorMessage(*appErrResult.Error)
		Debug(DbgInfo, "Application error received: %s\n", errStr)

		whiskErr := MakeWskError(errors.New(errStr), 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 getApplicationErrorMessage(errResp interface{}) string {
	var errStr string

	// Handle error results that looks like:
	//
	//   {
	//     "error": {
	//       "error": "An error string",
	//       "message": "An error message",
	//       "another-message": "Another error message"
	//     }
	//   }
	//   Returns "An error string; An error message; Another error message"
	//
	// OR
	//   {
	//     "error": "An error string"
	//   }
	//   Returns "An error string"
	//
	// OR
	//   {
	//     "error": {
	//       "custom-err": {
	//         "error": "An error string",
	//         "message": "An error message"
	//       }
	//     }
	//   }
	//   Returns "{"error": { "custom-err": { "error": "An error string", "message": "An error message" } } }"

	errMapIntf, errMapIntfOk := errResp.(map[string]interface{})
	if !errMapIntfOk {
		errStr = fmt.Sprintf("%v", errResp)
	} else {
		// Check if the "error" field in the response JSON
		errObjIntf, errObjIntfOk := errMapIntf["error"]
		if !errObjIntfOk {
			errStr = fmt.Sprintf("%v", errMapIntf)
		} else {
			// Check if the "error" field value is a JSON object
			errObj, errObjOk := errObjIntf.(map[string]interface{})
			if !errObjOk {
				// The "error" field value is not JSON; check if it's a string
				errorStr, errorStrOk := errObjIntf.(string)
				if !errorStrOk {
					errStr = fmt.Sprintf("%v", errObjIntf)
				} else {
					errStr = errorStr
				}
			} else {
				Debug(DbgInfo, "Application failure error json: %+v\n", errObj)

				// Concatenate all string field values into a single error string
				// Note: entry order of strings from map are not preserved.
				msgSeparator := ""
				for _, val := range errObj {
					valStr, valStrOk := val.(string)
					if valStrOk {
						errStr = errStr + msgSeparator + valStr
						msgSeparator = "; "
					}
				}

				// If no top level string fields exist, return the entire error object
				// Return a nice JSON string if possible; otherwise let Go try it's best
				if len(errStr) == 0 {
					jsonBytes, err := json.Marshal(errObj)
					if err != nil {
						errStr = fmt.Sprintf("%v", errObj)
					} else {
						errStr = string(jsonBytes)
					}
				}
			}
		}
	}

	return errStr
}
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 `json:"-"`     // 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  map[string]interface{} `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 errResp.Response != nil {
		return errResp.Response.Success
	} else if err != nil { //failed to parse WhiskErrorResponse
		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

	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
}
