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

import (
	"bufio"
	"errors"
	"fmt"
	"strings"

	"github.com/apache/incubator-openwhisk-cli/wski18n"
	"github.com/apache/incubator-openwhisk-client-go/whisk"

	"github.com/fatih/color"
	"github.com/mattn/go-colorable"

	//prettyjson "github.com/hokaccha/go-prettyjson"  // See prettyjson comment below
	"archive/tar"
	"archive/zip"
	"bytes"
	"compress/gzip"
	"encoding/json"
	"io"
	"io/ioutil"
	"os"
	"reflect"
	"regexp"
	"sort"
)

func csvToQualifiedActions(artifacts string) []string {
	var res []string
	actions := strings.Split(artifacts, ",")
	for i := 0; i < len(actions); i++ {
		res = append(res, getQualifiedName(actions[i], Properties.Namespace))
	}

	return res
}

/**
 * Processes command line to retrieve pairs of key-value pairs, where the value must be valid JSON.
 *
 * Parameters and annotations are handled the same way. The flag here is only for generating an error messages
 * specific to one or the other.
 *
 * NOTE: this function will exit in case of a processing error since it indicates a problem parsing parameters.
 *
 * @return either an array or a JSON object (map) formatted representation of the key-value pairs.
 */
func getParameters(params []string, keyValueFormat bool, annotation bool) interface{} {
	var parameters interface{}
	var err error

	if !annotation {
		whisk.Debug(whisk.DbgInfo, "Parsing parameters: %#v\n", params)
	} else {
		whisk.Debug(whisk.DbgInfo, "Parsing annotations: %#v\n", params)
	}

	parameters, err = getJSONFromStrings(params, keyValueFormat)
	if err != nil {
		whisk.Debug(whisk.DbgError, "getJSONFromStrings(%#v, %t) failed: %s\n", params, keyValueFormat, err)
		var errStr string

		if !annotation {
			errStr = wski18n.T("Invalid parameter argument '{{.param}}': {{.err}}",
				map[string]interface{}{"param": fmt.Sprintf("%#v", params), "err": err})
		} else {
			errStr = wski18n.T("Invalid annotation argument '{{.annotation}}': {{.err}}",
				map[string]interface{}{"annotation": fmt.Sprintf("%#v", params), "err": err})
		}
		werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		ExitOnError(werr)
	}

	return parameters
}

func getJSONFromStrings(content []string, keyValueFormat bool) (interface{}, error) {
	var data map[string]interface{}
	var res interface{}

	whisk.Debug(whisk.DbgInfo, "Convert content to JSON: %#v\n", content)

	for i := 0; i < len(content); i++ {
		dc := json.NewDecoder(strings.NewReader(content[i]))
		dc.UseNumber()
		if err := dc.Decode(&data); err != nil {
			whisk.Debug(whisk.DbgError, "Invalid JSON detected for '%s' \n", content[i])
			return whisk.KeyValueArr{}, err
		}

		whisk.Debug(whisk.DbgInfo, "Created map '%v' from '%v'\n", data, content[i])
	}

	if data == nil {
		data = make(map[string]interface{})
	}

	if keyValueFormat {
		res = getKeyValueFormattedJSON(data)
	} else {
		res = data
	}

	return res, nil
}

func getKeyValueFormattedJSON(data map[string]interface{}) whisk.KeyValueArr {
	var keyValueArr whisk.KeyValueArr

	for key, value := range data {
		keyValue := whisk.KeyValue{
			Key:   key,
			Value: value,
		}
		keyValueArr = append(keyValueArr, keyValue)
	}

	whisk.Debug(whisk.DbgInfo, "Created key/value format '%v' from '%v'\n", keyValueArr, data)

	return keyValueArr
}

func getFormattedJSON(key string, value string) string {
	var res string

	key = getEscapedJSON(key)

	if isValidJSON(value) {
		whisk.Debug(whisk.DbgInfo, "Value '%s' is valid JSON.\n", value)
		res = fmt.Sprintf("{\"%s\": %s}", key, value)
	} else {
		whisk.Debug(whisk.DbgInfo, "Converting value '%s' to a string as it is not valid JSON.\n", value)
		res = fmt.Sprintf("{\"%s\": \"%s\"}", key, value)
	}

	whisk.Debug(whisk.DbgInfo, "Formatted JSON '%s'\n", res)

	return res
}

func getEscapedJSON(value string) string {
	value = strings.Replace(value, "\\", "\\\\", -1)
	value = strings.Replace(value, "\"", "\\\"", -1)

	return value
}

func isValidJSON(value string) bool {
	var jsonInterface interface{}
	err := json.Unmarshal([]byte(value), &jsonInterface)

	return err == nil
}

var boldString = color.New(color.Bold).SprintFunc()

type Sortables []whisk.Sortable

// Uses quickSort to sort commands based on their compare methods
// Param: Takes in a array of Sortable interfaces which contains a specific command
func Swap(sortables Sortables, i, j int) { sortables[i], sortables[j] = sortables[j], sortables[i] }

func toPrintable(sortable []whisk.Sortable) []whisk.Printable {
	sortedPrintable := make([]whisk.Printable, len(sortable), len(sortable))
	for i := range sortable {
		sortedPrintable[i] = sortable[i].(whisk.Printable)
	}
	return sortedPrintable
}

// Prints the parameters/list for wsk xxxx list
// Identifies type and then copies array into an array of interfaces(Sortable) to be sorted and printed
// Param: Takes in an interface which contains an array of a command(Ex: []Action)
func printList(collection interface{}, sortByName bool) {
	var commandToSort []whisk.Sortable
	switch collection := collection.(type) {
	case []whisk.Action:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	case []whisk.Trigger:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	case []whisk.Package:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	case []whisk.Rule:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	case []whisk.Namespace:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	case []whisk.ActivationFilteredRow:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	case []whisk.ApiFilteredList:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	case []whisk.ApiFilteredRow:
		for i := range collection {
			commandToSort = append(commandToSort, collection[i])
		}
	}
	if sortByName && len(commandToSort) > 0 {
		quickSort(commandToSort, 0, len(commandToSort)-1)
	}
	printCommandsList(toPrintable(commandToSort), makeDefaultHeader(collection))
}

func quickSort(toSort Sortables, left int, right int) {
	low := left
	high := right
	pivot := toSort[(left+right)/2]

	for low <= high {
		for toSort[low].Compare(pivot) {
			low++
		}
		for pivot.Compare(toSort[high]) {
			high--
		}
		if low <= high {
			Swap(toSort, low, high)
			low++
			high--
		}
	}
	if left < high {
		quickSort(toSort, left, high)
	}
	if low < right {
		quickSort(toSort, low, right)
	}
}

// makeDefaultHeader(collection) returns the default header to be used in case
//      the list to be printed is empty.
func makeDefaultHeader(collection interface{}) string {
	defaultHeader := reflect.TypeOf(collection).String()
	defaultHeader = strings.ToLower(defaultHeader[8:] + "s") // Removes '[]whisk.' from `[]whisk.ENTITY_TYPE`
	if defaultHeader == "apifilteredrows" {
		defaultHeader = fmt.Sprintf("%-30s %7s %20s  %s", "Action", "Verb", "API Name", "URL")
	} else if defaultHeader == "apifilteredlists" {
		defaultHeader = ""
	} else if defaultHeader == "activationfilteredrows" {
		defaultHeader = ""
	}
	return defaultHeader
}

func stripTimestamp(log string) (strippedLog string) {
	// parses out the timestamp if it exists first
	// the timestamp expected format is YYYY-MM-DDTHH:MM:SS.[0-9]+Z
	// an optional " stdout" or " stderr" stream identifier
	// and the rest as the log line
	regex := regexp.MustCompile("\\d{4}-[01]{1}\\d{1}-[0-3]{1}\\d{1}T[0-2]{1}\\d{1}:[0-6]{1}\\d{1}:[0-6]{1}\\d{1}.\\d+Z( (stdout|stderr):)?\\s(.*)")
	match := regex.FindStringSubmatch(log)

	if len(match) > 3 && len(match[3]) > 0 {
		strippedLog = match[3]
	} else {
		strippedLog = log
	}

	return strippedLog
}

func printFullList(collection interface{}) {
	switch collection := collection.(type) {
	case []whisk.Action:

	case []whisk.Trigger:

	case []whisk.Package:

	case []whisk.Rule:

	case []whisk.Namespace:

	case []whisk.Activation:
		printFullActivationList(collection)
	}
}

func printSummary(collection interface{}) {
	switch collection := collection.(type) {
	case *whisk.Action:
		printActionSummary(collection)
	case *whisk.Trigger:
		printTriggerSummary(collection)
	case *whisk.Package:
		printPackageSummary(collection)
	case *whisk.Rule:

	case *whisk.Namespace:

	case *whisk.Activation:
	}
}

// Used to print Action, Tigger, Package, and Rule lists
// Param: Takes in a array of Printable interface, and the name of the command
//          being sent to it
// **Note**: The name should be an empty string for APIs.
func printCommandsList(commands []whisk.Printable, defaultHeader string) {
	if len(commands) != 0 {
		fmt.Fprint(color.Output, boldString(commands[0].ToHeaderString()))
		for i := range commands {
			fmt.Print(commands[i].ToSummaryRowString())
		}
	} else {
		fmt.Fprintf(color.Output, "%s\n", boldString(defaultHeader))
	}
}

func printFullActivationList(activations []whisk.Activation) {
	fmt.Fprintf(color.Output, "%s\n", boldString("activations"))
	for _, activation := range activations {
		printJSON(activation)
	}
}

func printStrippedActivationLogs(logs []string) {
	for _, log := range logs {
		fmt.Printf("%s\n", stripTimestamp(log))
	}
}

func printActivationLogs(logs []string) {
	for _, log := range logs {
		fmt.Printf("%s\n", log)
	}
}

func printArrayContents(arrStr []string) {
	for _, str := range arrStr {
		fmt.Printf("%s\n", str)
	}
}

func printPackageSummary(pkg *whisk.Package) {
	printEntitySummary(fmt.Sprintf("%7s", "package"), getFullName(pkg.Namespace, pkg.Name, ""),
		getValueString(pkg.Annotations, "description"),
		strings.Join(getParamUnion(pkg.Annotations, pkg.Parameters, "name"), ", "))

	if pkg.Actions != nil {
		for _, action := range pkg.Actions {
			paramUnion := getParamUnion(action.Annotations, action.Parameters, "name")
			printEntitySummary(fmt.Sprintf("%7s", "action"), getFullName(pkg.Namespace, pkg.Name, action.Name),
				getValueString(action.Annotations, "description"),
				strings.Join(paramUnion, ", "))
		}
	}

	if pkg.Feeds != nil {
		for _, feed := range pkg.Feeds {
			printEntitySummary(fmt.Sprintf("%7s", "feed  "), getFullName(pkg.Namespace, pkg.Name, feed.Name),
				getValueString(feed.Annotations, "description"),
				strings.Join(getParamUnion(feed.Annotations, feed.Parameters, "name"), ", "))
		}
	}
}

func printActionSummary(action *whisk.Action) {
	paramUnion := getParamUnion(action.Annotations, action.Parameters, "name")
	printEntitySummary(fmt.Sprintf("%6s", "action"),
		getFullName(action.Namespace, "", action.Name),
		getValueString(action.Annotations, "description"),
		strings.Join(paramUnion, ", "))
}

func printTriggerSummary(trigger *whisk.Trigger) {
	printEntitySummary(fmt.Sprintf("%7s", "trigger"),
		getFullName(trigger.Namespace, "", trigger.Name),
		getValueString(trigger.Annotations, "description"),
		strings.Join(getParamUnion(trigger.Annotations, trigger.Parameters, "name"), ", "))
}

func printRuleSummary(rule *whisk.Rule) {
	fmt.Fprintf(color.Output, "%s %s\n", boldString(fmt.Sprintf("%4s", "rule")),
		getFullName(rule.Namespace, "", rule.Name))
	fmt.Fprintf(color.Output, "   (%s: %s)\n", boldString(wski18n.T("status")), rule.Status)
}

func printEntitySummary(entityType string, fullName string, description string, params string) {
	emptyParams := "none defined"
	if len(params) <= 0 {
		params = emptyParams
	}
	if len(description) > 0 {
		fmt.Fprintf(color.Output, "%s %s: %s\n", boldString(entityType), fullName, description)
	} else if params != emptyParams {
		descriptionFromParams := buildParamDescription(params)
		fmt.Fprintf(color.Output, "%s %s: %s\n", boldString(entityType), fullName, descriptionFromParams)
	} else {
		fmt.Fprintf(color.Output, "%s %s\n", boldString(entityType), fullName)
	}
	fmt.Fprintf(color.Output, "   (%s: %s)\n", boldString(wski18n.T("parameters")), params)
}

//  getParamUnion(keyValArrAnnots, keyValArrParams, key) returns the union
//      of parameters listed under annotations (keyValArrAnnots, using key) and
//      bound parameters (keyValArrParams). Bound parameters will be denoted with
//      a prefixed "*", and finalized bound parameters (can't be changed by
//      user) will be denoted by a prefixed "**".
func getParamUnion(keyValArrAnnots whisk.KeyValueArr, keyValArrParams whisk.KeyValueArr, key string) []string {
	var res []string
	tag := "*"
	if getValueBool(keyValArrAnnots, "final") {
		tag = "**"
	}
	boundParams := getKeys(keyValArrParams)
	annotatedParams := getChildValueStrings(keyValArrAnnots, "parameters", key)
	res = append(boundParams, annotatedParams...) // Create union of boundParams and annotatedParams with duplication
	for i := 0; i < len(res); i++ {
		for j := i + 1; j < len(res); j++ {
			if res[i] == res[j] {
				res = append(res[:j], res[j+1:]...) // Remove duplicate entry
			}
		}
	}
	sort.Strings(res)
	res = tagBoundParams(boundParams, res, tag)
	return res
}

//  tagBoundParams(boundParams, paramUnion, tag) returns the list paramUnion with
//      all strings listed under boundParams set with a prefix tag.
func tagBoundParams(boundParams []string, paramUnion []string, tag string) []string {
	res := paramUnion
	for i := 0; i < len(boundParams); i++ {
		for j := 0; j < len(res); j++ {
			if boundParams[i] == res[j] {
				res[j] = fmt.Sprintf("%s%s", tag, res[j])
			}
		}
	}
	return res
}

//  buildParamDescription(params) returns a default entity description for
//      `$ wsk [ENTITY] get [ENTITY_NAME] --summary` when parameters are defined,
//      but the entity description under annotations is not.
func buildParamDescription(params string) string {
	preamble := "Returns a result based on parameter"
	params = strings.Replace(params, "*", "", -1)
	temp := strings.Split(params, ",")
	if len(temp) > 1 {
		lastParam := temp[len(temp)-1]
		newParams := strings.Replace(params, fmt.Sprintf(",%s", lastParam), fmt.Sprintf(" and%s", lastParam), 1)
		return fmt.Sprintf("%ss %s", preamble, newParams)
	}
	return fmt.Sprintf("%s %s", preamble, params)
}

func getFullName(namespace string, packageName string, entityName string) string {
	var fullName string

	if len(namespace) > 0 && len(packageName) > 0 && len(entityName) > 0 {
		fullName = fmt.Sprintf("/%s/%s/%s", namespace, packageName, entityName)
	} else if len(namespace) > 0 && len(packageName) > 0 {
		fullName = fmt.Sprintf("/%s/%s", namespace, packageName)
	} else if len(namespace) > 0 && len(entityName) > 0 {
		fullName = fmt.Sprintf("/%s/%s", namespace, entityName)
	} else if len(namespace) > 0 {
		fullName = fmt.Sprintf("/%s", namespace)
	}

	return fullName
}

func deleteKey(key string, keyValueArr whisk.KeyValueArr) whisk.KeyValueArr {
	for i := 0; i < len(keyValueArr); i++ {
		if keyValueArr[i].Key == key {
			keyValueArr = append(keyValueArr[:i], keyValueArr[i+1:]...)
			break
		}
	}

	return keyValueArr
}

func addKeyValue(key string, value interface{}, keyValueArr whisk.KeyValueArr) whisk.KeyValueArr {
	keyValue := whisk.KeyValue{
		Key:   key,
		Value: value,
	}

	return append(keyValueArr, keyValue)
}

func getKeys(keyValueArr whisk.KeyValueArr) []string {
	var res []string

	for i := 0; i < len(keyValueArr); i++ {
		res = append(res, keyValueArr[i].Key)
	}

	sort.Strings(res)
	whisk.Debug(whisk.DbgInfo, "Got keys '%v' from '%v'\n", res, keyValueArr)

	return res
}

func getValueString(keyValueArr whisk.KeyValueArr, key string) string {
	var value interface{}
	var res string

	value = keyValueArr.GetValue(key)
	castedValue, canCast := value.(string)

	if canCast {
		res = castedValue
	}

	whisk.Debug(whisk.DbgInfo, "Got string value '%v' for key '%s'\n", res, key)

	return res
}

func getValueBool(keyValueArr whisk.KeyValueArr, key string) bool {
	var value interface{}
	var res bool

	value = keyValueArr.GetValue(key)
	castedValue, canCast := value.(bool)

	if canCast {
		res = castedValue
	}

	whisk.Debug(whisk.DbgInfo, "Got bool value '%v' for key '%s'\n", res, key)

	return res
}

func getChildValues(keyValueArr whisk.KeyValueArr, key string, childKey string) []interface{} {
	var value interface{}
	var res []interface{}

	value = keyValueArr.GetValue(key)

	castedValue, canCast := value.([]interface{})
	if canCast {
		for i := 0; i < len(castedValue); i++ {
			castedValue, canCast := castedValue[i].(map[string]interface{})
			if canCast {
				for subKey, subValue := range castedValue {
					if subKey == childKey {
						res = append(res, subValue)
					}
				}
			}
		}
	}

	whisk.Debug(whisk.DbgInfo, "Got values '%s' from '%v' for key '%s' and child key '%s'\n", res, keyValueArr, key,
		childKey)

	return res
}

func getChildValueStrings(keyValueArr whisk.KeyValueArr, key string, childKey string) []string {
	var keys []interface{}
	var res []string

	keys = getChildValues(keyValueArr, key, childKey)

	for i := 0; i < len(keys); i++ {
		castedValue, canCast := keys[i].(string)
		if canCast {
			res = append(res, castedValue)
		}
	}

	sort.Strings(res)
	whisk.Debug(whisk.DbgInfo, "Got values '%s' from '%v' for key '%s' and child key '%s'\n", res, keyValueArr, key,
		childKey)

	return res
}

func getValueFromJSONResponse(field string, response map[string]interface{}) interface{} {
	var res interface{}

	for key, value := range response {
		if key == field {
			res = value
			break
		}
	}

	return res
}

func logoText() string {
	logo := `
        ____      ___                   _    _ _     _     _
       /\   \    / _ \ _ __   ___ _ __ | |  | | |__ (_)___| | __
  /\  /__\   \  | | | | '_ \ / _ \ '_ \| |  | | '_ \| / __| |/ /
 /  \____ \  /  | |_| | |_) |  __/ | | | |/\| | | | | \__ \   <
 \   \  /  \/    \___/| .__/ \___|_| |_|__/\__|_| |_|_|___/_|\_\
  \___\/ tm           |_|
`

	return logo
}

func printJSON(v interface{}, stream ...io.Writer) {
	// Can't use prettyjson util issue  https://github.com/hokaccha/go-prettyjson/issues/1 is fixed
	//output, _ := prettyjson.Marshal(v)
	//
	//if len(stream) > 0 {
	//    fmt.Fprintf(stream[0], string(output))
	//} else {
	//    fmt.Fprintf(color.Output, string(output))
	//}
	printJsonNoColor(v, stream...)
}

func printJsonNoColor(decoded interface{}, stream ...io.Writer) {
	var output bytes.Buffer

	buffer := new(bytes.Buffer)
	encoder := json.NewEncoder(buffer)
	encoder.SetEscapeHTML(false)
	encoder.Encode(&decoded)
	json.Indent(&output, buffer.Bytes(), "", "    ")

	if len(stream) > 0 {
		fmt.Fprintf(stream[0], "%s", string(output.Bytes()))
	} else {
		fmt.Fprintf(os.Stdout, "%s", string(output.Bytes()))
	}
}

func unpackGzip(inpath string, outpath string) error {
	var exists bool
	var err error

	exists, err = FileExists(outpath)

	if err != nil {
		return err
	}

	if exists {
		errStr := wski18n.T("The file '{{.name}}' already exists.  Delete it and retry.",
			map[string]interface{}{"name": outpath})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}

	exists, err = FileExists(inpath)

	if err != nil {
		return err
	}

	if !exists {
		errMsg := wski18n.T("File '{{.name}}' is not a valid file or it does not exist",
			map[string]interface{}{
				"name": inpath,
			})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_USAGE,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)

		return whiskErr
	}

	unGzFile, err := os.Create(outpath)
	if err != nil {
		whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", outpath, err)
		errStr := wski18n.T("Error creating unGzip file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": outpath, "err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}
	defer unGzFile.Close()

	gzFile, err := os.Open(inpath)
	if err != nil {
		whisk.Debug(whisk.DbgError, "os.Open(%s) failed: %s\n", inpath, err)
		errStr := wski18n.T("Error opening Gzip file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": inpath, "err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}
	defer gzFile.Close()

	gzReader, err := gzip.NewReader(gzFile)
	if err != nil {
		whisk.Debug(whisk.DbgError, "gzip.NewReader() failed: %s\n", err)
		errStr := wski18n.T("Unable to unzip file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": inpath, "err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}

	_, err = io.Copy(unGzFile, gzReader)
	if err != nil {
		whisk.Debug(whisk.DbgError, "io.Copy() failed: %s\n", err)
		errStr := wski18n.T("Unable to unzip file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": inpath, "err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}

	return nil
}

func unpackZip(inpath string) error {
	exists, err := FileExists(inpath)

	if err != nil {
		return err
	}

	if !exists {
		errMsg := wski18n.T("File '{{.name}}' is not a valid file or it does not exist",
			map[string]interface{}{
				"name": inpath,
			})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_USAGE,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)

		return whiskErr
	}
	zipFileReader, err := zip.OpenReader(inpath)
	if err != nil {
		whisk.Debug(whisk.DbgError, "zip.OpenReader(%s) failed: %s\n", inpath, err)
		errStr := wski18n.T("Unable to opens '{{.name}}' for unzipping: {{.err}}",
			map[string]interface{}{"name": inpath, "err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}
	defer zipFileReader.Close()

	// Loop through the files in the zipfile
	for _, item := range zipFileReader.File {
		itemName := item.Name
		itemType := item.Mode()

		whisk.Debug(whisk.DbgInfo, "file item - %#v\n", item)

		if itemType.IsDir() {
			if err := os.MkdirAll(item.Name, item.Mode()); err != nil {
				whisk.Debug(whisk.DbgError, "os.MkdirAll(%s, %d) failed: %s\n", item.Name, item.Mode(), err)
				errStr := wski18n.T("Unable to create directory '{{.dir}}' while unzipping '{{.name}}': {{.err}}",
					map[string]interface{}{"dir": item.Name, "name": inpath, "err": err})
				werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return werr
			}
		}

		if itemType.IsRegular() {
			unzipFile, err := item.Open()
			defer unzipFile.Close()
			if err != nil {
				whisk.Debug(whisk.DbgError, "'%s' Open() failed: %s\n", item.Name, err)
				errStr := wski18n.T("Unable to open zipped file '{{.file}}' while unzipping '{{.name}}': {{.err}}",
					map[string]interface{}{"file": item.Name, "name": inpath, "err": err})
				werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return werr
			}
			targetFile, err := os.Create(itemName)
			if err != nil {
				whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", itemName, err)
				errStr := wski18n.T("Unable to create file '{{.file}}' while unzipping '{{.name}}': {{.err}}",
					map[string]interface{}{"file": item.Name, "name": inpath, "err": err})
				werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return werr
			}
			if _, err := io.Copy(targetFile, unzipFile); err != nil {
				whisk.Debug(whisk.DbgError, "io.Copy() of '%s' failed: %s\n", itemName, err)
				errStr := wski18n.T("Unable to unzip file '{{.name}}': {{.err}}",
					map[string]interface{}{"name": itemName, "err": err})
				werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return werr
			}
		}
	}

	return nil
}

func unpackTar(inpath string) error {
	exists, err := FileExists(inpath)

	if err != nil {
		return err
	}

	if !exists {
		errMsg := wski18n.T("File '{{.name}}' is not a valid file or it does not exist",
			map[string]interface{}{
				"name": inpath,
			})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_USAGE,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)

		return whiskErr
	}

	tarFileReader, err := os.Open(inpath)
	if err != nil {
		whisk.Debug(whisk.DbgError, "os.Open(%s) failed: %s\n", inpath, err)
		errStr := wski18n.T("Error opening tar file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": inpath, "err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}
	defer tarFileReader.Close()

	// Loop through the files in the tarfile
	tReader := tar.NewReader(tarFileReader)
	for {
		item, err := tReader.Next()
		if err == io.EOF {
			whisk.Debug(whisk.DbgError, "EOF reach during untar\n")
			break // end of tar
		}
		if err != nil {
			whisk.Debug(whisk.DbgError, "tReader.Next() failed: %s\n", err)
			errStr := wski18n.T("Error reading tar file '{{.name}}': {{.err}}",
				map[string]interface{}{"name": inpath, "err": err})
			werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return werr
		}

		whisk.Debug(whisk.DbgInfo, "tar file item - %#v\n", item)
		switch item.Typeflag {
		case tar.TypeDir:
			if err := os.MkdirAll(item.Name, os.FileMode(item.Mode)); err != nil {
				whisk.Debug(whisk.DbgError, "os.MkdirAll(%s, %d) failed: %s\n", item.Name, item.Mode, err)
				errStr := wski18n.T("Unable to create directory '{{.dir}}' while untarring '{{.name}}': {{.err}}",
					map[string]interface{}{"dir": item.Name, "name": inpath, "err": err})
				werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return werr
			}
		case tar.TypeReg:
			untarFile, err := os.OpenFile(item.Name, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, os.FileMode(item.Mode))
			defer untarFile.Close()
			if err != nil {
				whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", item.Name, err)
				errStr := wski18n.T("Unable to create file '{{.file}}' while untarring '{{.name}}': {{.err}}",
					map[string]interface{}{"file": item.Name, "name": inpath, "err": err})
				werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return werr
			}
			if _, err := io.Copy(untarFile, tReader); err != nil {
				whisk.Debug(whisk.DbgError, "io.Copy() of '%s' failed: %s\n", item.Name, err)
				errStr := wski18n.T("Unable to untar file '{{.name}}': {{.err}}",
					map[string]interface{}{"name": item.Name, "err": err})
				werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
				return werr
			}
		default:
			whisk.Debug(whisk.DbgError, "Unexpected tar file type of %q\n", item.Typeflag)
			errStr := wski18n.T("Unable to untar '{{.name}}' due to unexpected tar file type\n",
				map[string]interface{}{"name": item.Name})
			werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return werr
		}
	}
	return nil
}

func CheckArgs(args []string, minimumArgNumber int, maximumArgNumber int, commandName string,
	requiredArgMsg string) *whisk.WskError {
	exactlyOrAtLeast := wski18n.T("exactly")
	exactlyOrNoMoreThan := wski18n.T("exactly")

	if minimumArgNumber != maximumArgNumber {
		exactlyOrAtLeast = wski18n.T("at least")
		exactlyOrNoMoreThan = wski18n.T("no more than")
	}

	if len(args) < minimumArgNumber {
		whisk.Debug(whisk.DbgError, fmt.Sprintf("%s command must have %s %d argument(s)\n", commandName,
			exactlyOrAtLeast, minimumArgNumber))
		errMsg := wski18n.T("Invalid argument(s). {{.required}}", map[string]interface{}{"required": requiredArgMsg})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr
	} else if len(args) > maximumArgNumber {
		whisk.Debug(whisk.DbgError, fmt.Sprintf("%s command must have %s %d argument(s)\n", commandName,
			exactlyOrNoMoreThan, maximumArgNumber))
		errMsg := wski18n.T("Invalid argument(s): {{.args}}. {{.required}}",
			map[string]interface{}{"args": strings.Join(args[maximumArgNumber:], ", "), "required": requiredArgMsg})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr
	} else {
		return nil
	}
}

func normalizeNamespace(namespace string) string {
	if namespace == "_" {
		namespace = wski18n.T("default")
	}

	return namespace
}

func getClientNamespace() string {
	return normalizeNamespace(Client.Config.Namespace)
}

func ReadFile(filename string) (string, error) {
	exists, err := FileExists(filename)

	if err != nil {
		return "", err
	}

	if !exists {
		errMsg := wski18n.T("File '{{.name}}' is not a valid file or it does not exist",
			map[string]interface{}{
				"name": filename,
			})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_USAGE,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)

		return "", whiskErr
	}

	file, err := ioutil.ReadFile(filename)
	if err != nil {
		whisk.Debug(whisk.DbgError, "os.ioutil.ReadFile(%s) error: %s\n", filename, err)
		errMsg := wski18n.T("Unable to read the file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": filename, "err": err})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return "", whiskErr
	}

	return string(file), nil
}

func writeFile(filename string, content string) error {
	file, err := os.Create(filename)

	if err != nil {
		whisk.Debug(whisk.DbgError, "os.Create(%s) error: %#v\n", filename, err)
		errMsg := wski18n.T("Cannot create file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": filename, "err": err})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_USAGE, whisk.DISPLAY_MSG,
			whisk.DISPLAY_USAGE)
		return whiskErr
	}

	defer file.Close()

	if _, err = file.WriteString(content); err != nil {
		whisk.Debug(whisk.DbgError, "File.WriteString(%s) error: %#v\n", content, err)
		errMsg := wski18n.T("Cannot create file '{{.name}}': {{.err}}",
			map[string]interface{}{"name": filename, "err": err})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_USAGE, whisk.DISPLAY_MSG,
			whisk.DISPLAY_USAGE)
		return whiskErr
	}

	return nil
}

func FileExists(file string) (bool, error) {
	_, err := os.Stat(file)

	if err != nil {
		if os.IsNotExist(err) == true {
			return false, nil
		} else {
			whisk.Debug(whisk.DbgError, "os.Stat(%s) error: %#v\n", file, err)
			errMsg := wski18n.T("Cannot access file '{{.name}}': {{.err}}",
				map[string]interface{}{"name": file, "err": err})
			whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_USAGE,
				whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
			return true, whiskErr
		}
	}

	return true, nil
}

func fieldExists(value interface{}, field string) bool {
	element := reflect.ValueOf(value).Elem()

	for i := 0; i < element.NumField(); i++ {
		if strings.ToLower(element.Type().Field(i).Name) == strings.ToLower(field) {
			return true
		}
	}

	return false
}

func printField(value interface{}, field string) {
	var matchFunc = func(structField string) bool {
		return strings.ToLower(structField) == strings.ToLower(field)
	}

	structValue := reflect.ValueOf(value)
	fieldValue := reflect.Indirect(structValue).FieldByNameFunc(matchFunc)

	printJSON(fieldValue.Interface())
}

func parseShared(shared string) (bool, bool, error) {
	var isShared, isSet bool

	if strings.ToLower(shared) == "yes" {
		isShared = true
		isSet = true
	} else if strings.ToLower(shared) == "no" {
		isShared = false
		isSet = true
	} else if len(shared) == 0 {
		isSet = false
	} else {
		whisk.Debug(whisk.DbgError, "Cannot use value '%s' for shared.\n", shared)
		errMsg := wski18n.T("Cannot use value '{{.arg}}' for shared.", map[string]interface{}{"arg": shared})
		whiskErr := whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG,
			whisk.DISPLAY_USAGE)
		return false, false, whiskErr
	}

	whisk.Debug(whisk.DbgError, "Sharing is '%t'\n", isShared)

	return isShared, isSet, nil
}

func max(a int, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a int, b int) int {
	if a < b {
		return a
	}
	return b
}

func ReadProps(path string) (map[string]string, error) {

	props := map[string]string{}

	file, err := os.Open(path)
	if err != nil {
		// If file does not exist, just return props
		whisk.Debug(whisk.DbgWarn, "Unable to read whisk properties file '%s' (file open error: %s); falling back to default properties\n", path, err)
		return props, nil
	}
	defer file.Close()

	lines := []string{}
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	props = map[string]string{}
	for _, line := range lines {
		re := regexp.MustCompile("#.*")
		line = re.ReplaceAllString(line, "")
		line = strings.TrimSpace(line)
		kv := strings.Split(line, "=")
		if len(kv) != 2 {
			// Invalid format; skip
			continue
		}
		props[kv[0]] = kv[1]
	}

	return props, nil

}

func WriteProps(path string, props map[string]string) error {

	file, err := os.Create(path)
	if err != nil {
		whisk.Debug(whisk.DbgError, "os.Create(%s) failed: %s\n", path, err)
		errStr := wski18n.T("Whisk properties file write failure: {{.err}}", map[string]interface{}{"err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return werr
	}
	defer file.Close()

	writer := bufio.NewWriter(file)
	defer writer.Flush()
	for key, value := range props {
		line := fmt.Sprintf("%s=%s", strings.ToUpper(key), value)
		_, err = fmt.Fprintln(writer, line)
		if err != nil {
			whisk.Debug(whisk.DbgError, "fmt.Fprintln() write to '%s' failed: %s\n", path, err)
			errStr := wski18n.T("Whisk properties file write failure: {{.err}}", map[string]interface{}{"err": err})
			werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
			return werr
		}
	}
	return nil
}

func getSpaceGuid() (string, error) {
	// get current props
	props, err := ReadProps(Properties.PropsFile)
	if err != nil {
		whisk.Debug(whisk.DbgError, "readProps(%s) failed: %s\n", Properties.PropsFile, err)
		errStr := wski18n.T("Unable to obtain the `auth` property value: {{.err}}", map[string]interface{}{"err": err})
		werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return "", werr
	}

	// get the auth key and parse out the space guid
	if authToken, hasProp := props["AUTH"]; hasProp {
		spaceGuid := strings.Split(authToken, ":")[0]
		return spaceGuid, nil
	}

	whisk.Debug(whisk.DbgError, "auth not found in properties: %#q\n", props)
	errStr := wski18n.T("Auth key property value is not set")
	werr := whisk.MakeWskError(errors.New(errStr), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
	return "", werr
}

func isBlockingTimeout(err error) bool {
	var blockingTimeout bool

	whiskErr, isWhiskErr := err.(*whisk.WskError)

	if isWhiskErr && whiskErr.TimedOut {
		blockingTimeout = true
	}

	return blockingTimeout
}

func isApplicationError(err error) bool {
	var applicationError bool

	whiskErr, isWhiskErr := err.(*whisk.WskError)

	if isWhiskErr && whiskErr.ApplicationError {
		applicationError = true
	}

	return applicationError
}

func contains(arr []string, element string) bool {
	for _, e := range arr {
		if e == element {
			return true
		}
	}
	return false
}

func ExitOnError(err error) {
	if err == nil {
		return
	}

	whisk.Debug(whisk.DbgInfo, "err object type: %s\n", reflect.TypeOf(err).String())

	T := wski18n.T
	var exitCode int = 0
	var displayUsage bool = false
	var displayMsg bool = false
	var msgDisplayed bool = true
	var displayPrefix bool = true

	werr, isWskError := err.(*whisk.WskError) // Is the err a WskError?
	if isWskError {
		whisk.Debug(whisk.DbgError, "Got a *whisk.WskError error: %#v\n", werr)
		displayUsage = werr.DisplayUsage
		displayMsg = werr.DisplayMsg
		msgDisplayed = werr.MsgDisplayed
		displayPrefix = werr.DisplayPrefix
		exitCode = werr.ExitCode
	} else {
		whisk.Debug(whisk.DbgError, "Got some other error: %s\n", err)
		fmt.Fprintf(os.Stderr, "%s\n", err)

		displayUsage = false // Cobra already displayed the usage message
		exitCode = 1
	}

	outputStream := colorable.NewColorableStderr()

	// If the err msg should be displayed to the console and it has not already been
	// displayed, display it now.
	if displayMsg && !msgDisplayed && displayPrefix && exitCode != 0 {
		fmt.Fprintf(outputStream, "%s%s\n", color.RedString(T("error: ")), err)
	} else if displayMsg && !msgDisplayed && !displayPrefix && exitCode != 0 {
		fmt.Fprintf(outputStream, "%s\n", err)
	} else if displayMsg && !msgDisplayed && exitCode == 0 {
		fmt.Fprintf(outputStream, "%s\n", err)
	}

	// Displays usage
	if displayUsage {
		fmt.Fprintf(outputStream, T("Run '{{.Name}} --help' for usage.\n",
			map[string]interface{}{"Name": WskCmd.CommandPath()}))
	}

	os.Exit(exitCode)
}
