/*
 * 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 (
	"errors"
	"net/http"
	"os"
	"runtime"

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

	"github.com/spf13/cobra"
)

var Client *whisk.Client

const DefaultOpenWhiskApiPath string = "/api"

var UserAgent string = "OpenWhisk-CLI"
var AdditionalHeaders http.Header

func SetupClientConfig(cmd *cobra.Command, args []string) error {
	baseURL, err := whisk.GetURLBase(Properties.APIHost, DefaultOpenWhiskApiPath)

	// Determine if the parent command will require the API host to be set
	apiHostRequired := (cmd.Parent().Name() == "property" && cmd.Name() == "get" && (Flags.property.auth ||
		Flags.property.cert || Flags.property.key || Flags.property.apihost ||
		Flags.property.apiversion || Flags.property.cliversion)) ||
		(cmd.Parent().Name() == "property" && cmd.Name() == "set" && (len(Flags.property.apihostSet) > 0 ||
			len(Flags.property.apiversionSet) > 0 || len(Flags.Global.Auth) > 0)) ||
		(cmd.Parent().Name() == "sdk" && cmd.Name() == "install" && len(args) > 0 && args[0] == "bashauto")

	// Display an error if the parent command requires an API host to be set, and the current API host is not valid
	if err != nil && !apiHostRequired {
		whisk.Debug(whisk.DbgError, "whisk.GetURLBase(%s, %s) error: %s\n", Properties.APIHost, DefaultOpenWhiskApiPath, err)
		errMsg := wski18n.T("The API host is not valid: {{.err}}", map[string]interface{}{"err": err})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE)
		return whiskErr
	}

	clientConfig := &whisk.Config{
		Cert:              Properties.Cert,
		Key:               Properties.Key,
		AuthToken:         Properties.Auth,
		Namespace:         Properties.Namespace,
		BaseURL:           baseURL,
		Version:           Properties.APIVersion,
		Insecure:          Flags.Global.Insecure,
		Host:              Properties.APIHost,
		UserAgent:         UserAgent + "/1.0 (" + Properties.CLIVersion + ") " + runtime.GOOS + " " + runtime.GOARCH,
		AdditionalHeaders: AdditionalHeaders,
	}

	if len(clientConfig.Host) == 0 {
		config, _ := whisk.GetDefaultConfig()
		clientConfig.Host = config.Host
		if len(clientConfig.Host) == 0 {
			clientConfig.Host = "openwhisk.ng.bluemix.net"
		}
	}

	// Setup client
	Client, err = whisk.NewClient(http.DefaultClient, clientConfig)

	if err != nil {
		whisk.Debug(whisk.DbgError, "whisk.NewClient(%#v, %#v) error: %s\n", http.DefaultClient, clientConfig, err)
		errMsg := wski18n.T("Unable to initialize server connection: {{.err}}", map[string]interface{}{"err": err})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr
	}

	return nil
}

func init() {}

func getKeyValueArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) {
	var whiskErr error
	var key string
	var value string

	if len(args)-1 >= argIndex+2 {
		key = args[argIndex+1]
		value = args[argIndex+2]
		parsedArgs = append(parsedArgs, getFormattedJSON(key, value))
		args = append(args[:argIndex], args[argIndex+3:]...)
	} else {
		whisk.Debug(whisk.DbgError, "Arguments for '%s' must be a key/value pair; args: %s", args[argIndex], args)
		errMsg := wski18n.T("Arguments for '{{.arg}}' must be a key/value pair",
			map[string]interface{}{"arg": args[argIndex]})
		whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG,
			whisk.DISPLAY_USAGE)
	}

	return parsedArgs, args, whiskErr
}

func getValueFromArgs(args []string, argIndex int, parsedArgs []string) ([]string, []string, error) {
	var whiskErr error

	if len(args)-1 >= argIndex+1 {
		parsedArgs = append(parsedArgs, args[argIndex+1])
		args = append(args[:argIndex], args[argIndex+2:]...)
	} else {
		whisk.Debug(whisk.DbgError, "An argument must be provided for '%s'; args: %s", args[argIndex], args)
		errMsg := wski18n.T("An argument must be provided for '{{.arg}}'",
			map[string]interface{}{"arg": args[argIndex]})
		whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG,
			whisk.DISPLAY_USAGE)
	}

	return parsedArgs, args, whiskErr
}

func parseArgs(args []string) ([]string, []string, []string, error) {
	var paramArgs []string
	var annotArgs []string
	var whiskErr error

	i := 0

	for i < len(args) {
		if args[i] == "-P" || args[i] == "--param-file" {
			paramArgs, args, whiskErr = getValueFromArgs(args, i, paramArgs)
			if whiskErr != nil {
				whisk.Debug(whisk.DbgError, "getValueFromArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
				errMsg := wski18n.T("The parameter arguments are invalid: {{.err}}",
					map[string]interface{}{"err": whiskErr})
				whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG,
					whisk.DISPLAY_USAGE)
				return nil, nil, nil, whiskErr
			}

			filename := paramArgs[len(paramArgs)-1]
			paramArgs[len(paramArgs)-1], whiskErr = ReadFile(filename)
			if whiskErr != nil {
				whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr)
				return nil, nil, nil, whiskErr
			}
		} else if args[i] == "-A" || args[i] == "--annotation-file" {
			annotArgs, args, whiskErr = getValueFromArgs(args, i, annotArgs)
			if whiskErr != nil {
				whisk.Debug(whisk.DbgError, "getValueFromArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
				errMsg := wski18n.T("The annotation arguments are invalid: {{.err}}",
					map[string]interface{}{"err": whiskErr})
				whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG,
					whisk.DISPLAY_USAGE)
				return nil, nil, nil, whiskErr
			}

			filename := annotArgs[len(annotArgs)-1]
			annotArgs[len(annotArgs)-1], whiskErr = ReadFile(filename)
			if whiskErr != nil {
				whisk.Debug(whisk.DbgError, "readFile(%s) error: %s\n", filename, whiskErr)
				return nil, nil, nil, whiskErr
			}
		} else if args[i] == "-p" || args[i] == "--param" {
			paramArgs, args, whiskErr = getKeyValueArgs(args, i, paramArgs)
			if whiskErr != nil {
				whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
				errMsg := wski18n.T("The parameter arguments are invalid: {{.err}}",
					map[string]interface{}{"err": whiskErr})
				whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG,
					whisk.DISPLAY_USAGE)
				return nil, nil, nil, whiskErr
			}
		} else if args[i] == "-a" || args[i] == "--annotation" {
			annotArgs, args, whiskErr = getKeyValueArgs(args, i, annotArgs)
			if whiskErr != nil {
				whisk.Debug(whisk.DbgError, "getKeyValueArgs(%#v, %d) failed: %s\n", args, i, whiskErr)
				errMsg := wski18n.T("The annotation arguments are invalid: {{.err}}",
					map[string]interface{}{"err": whiskErr})
				whiskErr = whisk.MakeWskError(errors.New(errMsg), whisk.EXIT_CODE_ERR_GENERAL, whisk.DISPLAY_MSG,
					whisk.DISPLAY_USAGE)
				return nil, nil, nil, whiskErr
			}
		} else {
			i++
		}
	}

	whisk.Debug(whisk.DbgInfo, "Found param args '%s'.\n", paramArgs)
	whisk.Debug(whisk.DbgInfo, "Found annotations args '%s'.\n", annotArgs)
	whisk.Debug(whisk.DbgInfo, "Arguments with param args removed '%s'.\n", args)

	return args, paramArgs, annotArgs, nil
}

func Execute() error {
	var err error

	whisk.Debug(whisk.DbgInfo, "wsk args: %#v\n", os.Args)
	os.Args, Flags.common.param, Flags.common.annotation, err = parseArgs(os.Args)

	if err != nil {
		whisk.Debug(whisk.DbgError, "parseParams(%s) failed: %s\n", os.Args, err)
		errMsg := wski18n.T("Failed to parse arguments: {{.err}}", map[string]interface{}{"err": err})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr
	}

	err = loadProperties()
	if err != nil {
		whisk.Debug(whisk.DbgError, "loadProperties() error: %s\n", err)
		errMsg := wski18n.T("Unable to access configuration properties: {{.err}}", map[string]interface{}{"err": err})
		whiskErr := whisk.MakeWskErrorFromWskError(errors.New(errMsg), err, whisk.EXIT_CODE_ERR_GENERAL,
			whisk.DISPLAY_MSG, whisk.DISPLAY_USAGE)
		return whiskErr
	}

	return WskCmd.Execute()
}
