/*
 * 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/openwhisk-cli/wski18n"
	"github.com/apache/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)
}
