/*
 * 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 (
	"errors"
	"fmt"
	"github.com/apache/openwhisk-client-go/wski18n"
	"net/http"
	"net/url"
	"strings"
)

type ActionService struct {
	client ClientInterface
}

type Action struct {
	Namespace      string      `json:"namespace,omitempty"`
	Name           string      `json:"name,omitempty"`
	Version        string      `json:"version,omitempty"`
	Exec           *Exec       `json:"exec,omitempty"`
	Annotations    KeyValueArr `json:"annotations,omitempty"`
	DelAnnotations []string    `json:"delAnnotations,omitempty"`
	Parameters     KeyValueArr `json:"parameters,omitempty"`
	Limits         *Limits     `json:"limits,omitempty"`
	Error          string      `json:"error,omitempty"`
	Code           int         `json:"code,omitempty"`
	Publish        *bool       `json:"publish,omitempty"`
	Updated        int64       `json:"updated,omitempty"`
}

type Exec struct {
	Kind       string   `json:"kind,omitempty"`
	Code       *string  `json:"code,omitempty"`
	Image      string   `json:"image,omitempty"`
	Init       string   `json:"init,omitempty"`
	Main       string   `json:"main,omitempty"`
	Components []string `json:"components,omitempty"` // List of fully qualified actions
	Binary     *bool    `json:"binary,omitempty"`
}

type ActionListOptions struct {
	Limit int  `url:"limit"`
	Skip  int  `url:"skip"`
	Docs  bool `url:"docs,omitempty"`
}

// Compare(sortable) compares action to sortable for the purpose of sorting.
// REQUIRED: sortable must also be of type Action.
// ***Method of type Sortable***
func (action Action) Compare(sortable Sortable) bool {
	// Sorts alphabetically by NAMESPACE -> PACKAGE_NAME -> ACTION_NAME, with
	//    actions under default package at the top.
	var actionString string
	var compareString string
	actionToCompare := sortable.(Action)

	actionString = strings.ToLower(fmt.Sprintf("%s%s", action.Namespace, action.Name))
	compareString = strings.ToLower(fmt.Sprintf("%s%s", actionToCompare.Namespace,
		actionToCompare.Name))
	if strings.Contains(action.Namespace, "/") && !strings.Contains(actionToCompare.Namespace, "/") {
		return false
	} else if !strings.Contains(action.Namespace, "/") && strings.Contains(actionToCompare.Namespace, "/") {
		return true
	} else if strings.Contains(action.Namespace, "/") && strings.Contains(actionToCompare.Namespace, "/") {
		return actionString < compareString
	} else {
		return action.Name < actionToCompare.Name
	}
}

// ToHeaderString() returns the header for a list of actions
func (action Action) ToHeaderString() string {
	return fmt.Sprintf("%s\n", "actions")
}

// ToSummaryRowString() returns a compound string of required parameters for printing
//   from CLI command `wsk action list`.
// ***Method of type Sortable***
func (action Action) ToSummaryRowString() string {
	var kind string
	publishState := wski18n.T("private")

	for i := range action.Annotations {
		if action.Annotations[i].Key == "exec" {
			kind = action.Annotations[i].Value.(string)
			break
		}
	}
	return fmt.Sprintf("%-70s %s %s\n", fmt.Sprintf("/%s/%s", action.Namespace, action.Name), publishState, kind)
}

/*
Determines if an action is a web action by examining the action's annotations. A value of true is returned if the
action's annotations contains a "web-export" key and its associated value is a boolean value of "true". Otherwise, false
is returned.
*/
func (action Action) WebAction() (webExportValue bool) {
	webExport := action.Annotations.GetValue("web-export")
	webExportValue, _ = webExport.(bool)

	Debug(DbgInfo, "Web export value is '%t'\n", webExportValue)

	return webExportValue
}

/*
Returns the URL of an action as a string. A valid API host, path and version must be passed. A package that contains the
action must be passed as well. An empty string must be passed if the action is not packaged.
*/
func (action Action) ActionURL(apiHost string, apiPath string, apiVersion string, pkg string) (string, error) {
	baseURL, err := GetURLBase(apiHost, apiPath)
	if err != nil {
		Debug(DbgError, "GetURLBase(%s, %s) failed: %s\n", apiHost, apiPath, err)
		return "", err
	}
	webActionPath := "%s/%s/web/%s/%s/%s"
	actionPath := "%s/%s/namespaces/%s/actions/%s"
	packagedActionPath := actionPath + "/%s"
	namespace := strings.Split(action.Namespace, "/")[0]
	namespace = strings.Replace(url.QueryEscape(namespace), "+", "%20", -1)
	name := strings.Replace(url.QueryEscape(action.Name), "+", "%20", -1)
	pkg = strings.Replace(url.QueryEscape(pkg), "+", "%20", -1)

	var actionURL string
	if action.WebAction() {
		if len(pkg) == 0 {
			pkg = "default"
		}

		actionURL = fmt.Sprintf(webActionPath, baseURL, apiVersion, namespace, pkg, name)
		Debug(DbgInfo, "Web action URL: %s\n", actionURL)
	} else {
		if len(pkg) == 0 {
			actionURL = fmt.Sprintf(actionPath, baseURL, apiVersion, namespace, name)
			Debug(DbgInfo, "Packaged action URL: %s\n", actionURL)
		} else {
			actionURL = fmt.Sprintf(packagedActionPath, baseURL, apiVersion, namespace, pkg, name)
			Debug(DbgInfo, "Action URL: %s\n", actionURL)
		}
	}

	return actionURL, nil
}

////////////////////
// Action Methods //
////////////////////

func (s *ActionService) List(packageName string, options *ActionListOptions) ([]Action, *http.Response, error) {
	var route string
	var actions []Action

	if len(packageName) > 0 {
		// Encode resource name as a path (with no query params) before inserting it into the URI
		// This way any '?' chars in the name won't be treated as the beginning of the query params
		packageName = (&url.URL{Path: packageName}).String()
		route = fmt.Sprintf("actions/%s/", packageName)
	} else {
		route = fmt.Sprintf("actions")
	}

	routeUrl, err := addRouteOptions(route, options)
	if err != nil {
		Debug(DbgError, "addRouteOptions(%s, %#v) error: '%s'\n", route, options, err)
		errMsg := wski18n.T("Unable to add route options '{{.options}}'",
			map[string]interface{}{"options": options})
		whiskErr := MakeWskErrorFromWskError(errors.New(errMsg), err, EXIT_CODE_ERR_GENERAL, DISPLAY_MSG,
			NO_DISPLAY_USAGE)
		return nil, nil, whiskErr
	}
	Debug(DbgError, "Action list route with options: %s\n", route)

	req, err := s.client.NewRequestUrl("GET", routeUrl, nil, IncludeNamespaceInUrl, AppendOpenWhiskPathPrefix, EncodeBodyAsJson, AuthRequired)
	if err != nil {
		Debug(DbgError, "http.NewRequestUrl(GET, %s, nil, IncludeNamespaceInUrl, AppendOpenWhiskPathPrefix, EncodeBodyAsJson, AuthRequired) error: '%s'\n", routeUrl, err)
		errMsg := wski18n.T("Unable to create HTTP request for GET '{{.route}}': {{.err}}",
			map[string]interface{}{"route": routeUrl, "err": err})
		whiskErr := MakeWskErrorFromWskError(errors.New(errMsg), err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG,
			NO_DISPLAY_USAGE)
		return nil, nil, whiskErr
	}

	resp, err := s.client.Do(req, &actions, ExitWithSuccessOnTimeout)
	if err != nil {
		Debug(DbgError, "s.client.Do() error - HTTP req %s; error '%s'\n", req.URL.String(), err)
		return nil, resp, err
	}

	return actions, resp, err
}

func (s *ActionService) Insert(action *Action, overwrite bool) (*Action, *http.Response, error) {
	// Encode resource name as a path (with no query params) before inserting it into the URI
	// This way any '?' chars in the name won't be treated as the beginning of the query params
	actionName := (&url.URL{Path: action.Name}).String()
	route := fmt.Sprintf("actions/%s?overwrite=%t", actionName, overwrite)
	Debug(DbgInfo, "Action insert route: %s\n", route)

	req, err := s.client.NewRequest("PUT", route, action, IncludeNamespaceInUrl)
	if err != nil {
		Debug(DbgError, "http.NewRequest(PUT, %s, %#v) error: '%s'\n", route, action, err)
		errMsg := wski18n.T("Unable to create HTTP request for PUT '{{.route}}': {{.err}}",
			map[string]interface{}{"route": route, "err": err})
		whiskErr := MakeWskErrorFromWskError(errors.New(errMsg), err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG,
			NO_DISPLAY_USAGE)
		return nil, nil, whiskErr
	}

	a := new(Action)
	resp, err := s.client.Do(req, &a, ExitWithSuccessOnTimeout)
	if err != nil {
		Debug(DbgError, "s.client.Do() error - HTTP req %s; error '%s'\n", req.URL.String(), err)
		return nil, resp, err
	}

	return a, resp, nil
}

func (s *ActionService) Get(actionName string, fetchCode bool) (*Action, *http.Response, error) {
	// Encode resource name as a path (with no query params) before inserting it into the URI
	// This way any '?' chars in the name won't be treated as the beginning of the query params
	actionName = (&url.URL{Path: actionName}).String()
	route := fmt.Sprintf("actions/%s?code=%t", actionName, fetchCode)

	req, err := s.client.NewRequest("GET", route, nil, IncludeNamespaceInUrl)
	if err != nil {
		Debug(DbgError, "http.NewRequest(GET, %s, nil) error: '%s'\n", route, err)
		errMsg := wski18n.T("Unable to create HTTP request for GET '{{.route}}': {{.err}}",
			map[string]interface{}{"route": route, "err": err})
		whiskErr := MakeWskErrorFromWskError(errors.New(errMsg), err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG,
			NO_DISPLAY_USAGE)
		return nil, nil, whiskErr
	}

	a := new(Action)
	resp, err := s.client.Do(req, &a, ExitWithSuccessOnTimeout)
	if err != nil {
		Debug(DbgError, "s.client.Do() error - HTTP req %s; error '%s'\n", req.URL.String(), err)
		return nil, resp, err
	}

	return a, resp, nil
}

func (s *ActionService) Delete(actionName string) (*http.Response, error) {
	// Encode resource name as a path (with no query params) before inserting it into the URI
	// This way any '?' chars in the name won't be treated as the beginning of the query params
	actionName = (&url.URL{Path: actionName}).String()
	route := fmt.Sprintf("actions/%s", actionName)
	Debug(DbgInfo, "HTTP route: %s\n", route)

	req, err := s.client.NewRequest("DELETE", route, nil, IncludeNamespaceInUrl)
	if err != nil {
		Debug(DbgError, "http.NewRequest(DELETE, %s, nil) error: '%s'\n", route, err)
		errMsg := wski18n.T("Unable to create HTTP request for DELETE '{{.route}}': {{.err}}",
			map[string]interface{}{"route": route, "err": err})
		whiskErr := MakeWskErrorFromWskError(errors.New(errMsg), err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG,
			NO_DISPLAY_USAGE)
		return nil, whiskErr
	}

	a := new(Action)
	resp, err := s.client.Do(req, a, ExitWithSuccessOnTimeout)
	if err != nil {
		Debug(DbgError, "s.client.Do() error - HTTP req %s; error '%s'\n", req.URL.String(), err)
		return resp, err
	}

	return resp, nil
}

func (s *ActionService) Invoke(actionName string, payload interface{}, blocking bool, result bool) (map[string]interface{}, *http.Response, error) {
	var res map[string]interface{}

	// Encode resource name as a path (with no query params) before inserting it into the URI
	// This way any '?' chars in the name won't be treated as the beginning of the query params
	actionName = (&url.URL{Path: actionName}).String()
	route := fmt.Sprintf("actions/%s?blocking=%t&result=%t", actionName, blocking, result)
	Debug(DbgInfo, "HTTP route: %s\n", route)

	req, err := s.client.NewRequest("POST", route, payload, IncludeNamespaceInUrl)
	if err != nil {
		Debug(DbgError, "http.NewRequest(POST, %s, %#v) error: '%s'\n", route, payload, err)
		errMsg := wski18n.T("Unable to create HTTP request for POST '{{.route}}': {{.err}}",
			map[string]interface{}{"route": route, "err": err})
		whiskErr := MakeWskErrorFromWskError(errors.New(errMsg), err, EXIT_CODE_ERR_NETWORK, DISPLAY_MSG,
			NO_DISPLAY_USAGE)
		return nil, nil, whiskErr
	}

	resp, err := s.client.Do(req, &res, blocking)

	if err != nil {
		Debug(DbgError, "s.client.Do() error - HTTP req %s; error '%s'\n", req.URL.String(), err)
		return res, resp, err
	}

	return res, resp, nil
}
