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

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)

	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)

	return req, nil
}
