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

import (
	"encoding/base64"
	"errors"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v2"

	"github.com/apache/incubator-openwhisk-client-go/whisk"
	"github.com/apache/incubator-openwhisk-wskdeploy/conductor"
	"github.com/apache/incubator-openwhisk-wskdeploy/dependencies"
	"github.com/apache/incubator-openwhisk-wskdeploy/runtimes"
	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
	"github.com/apache/incubator-openwhisk-wskdeploy/webaction"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskenv"
	"github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
	"net/url"
)

const (
	API                   = "API"
	HTTPS                 = "https://"
	HTTP                  = "http://"
	API_VERSION           = "v1"
	WEB                   = "web"
	PATH_SEPARATOR        = "/"
	DEFAULT_PACKAGE       = "default"
	NATIVE_DOCKER_IMAGE   = "openwhisk/dockerskeleton"
	PARAM_OPENING_BRACKET = "{"
	PARAM_CLOSING_BRACKET = "}"
)

// Read existing manifest file or create new if none exists
func ReadOrCreateManifest() (*YAML, error) {
	maniyaml := YAML{}

	if _, err := os.Stat(utils.ManifestFileNameYaml); err == nil {
		dat, _ := ioutil.ReadFile(utils.ManifestFileNameYaml)
		err := NewYAMLParser().Unmarshal(dat, &maniyaml)
		if err != nil {
			return &maniyaml, wskderrors.NewFileReadError(utils.ManifestFileNameYaml, err.Error())
		}
	}
	return &maniyaml, nil
}

// Serialize manifest to local file
func Write(manifest *YAML, filename string) error {
	output, err := NewYAMLParser().marshal(manifest)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(filename, err.Error())
	}

	f, err := os.Create(filename)
	if err != nil {
		return wskderrors.NewFileReadError(filename, err.Error())
	}
	defer f.Close()

	f.Write(output)
	return nil
}

func (dm *YAMLParser) Unmarshal(input []byte, manifest *YAML) error {
	err := yaml.UnmarshalStrict(input, manifest)
	if err != nil {
		return err
	}
	return nil
}

func (dm *YAMLParser) marshal(manifest *YAML) (output []byte, err error) {
	data, err := yaml.Marshal(manifest)
	if err != nil {
		return nil, err
	}
	return data, nil
}

func (dm *YAMLParser) ParseManifest(manifestPath string) (*YAML, error) {
	mm := NewYAMLParser()
	maniyaml := YAML{}

	content, err := utils.Read(manifestPath)
	if err != nil {
		return &maniyaml, wskderrors.NewFileReadError(manifestPath, err.Error())
	}

	err = mm.Unmarshal(content, &maniyaml)
	if err != nil {
		return &maniyaml, wskderrors.NewYAMLParserErr(manifestPath, err)
	}
	maniyaml.Filepath = manifestPath
	manifest := ReadEnvVariable(&maniyaml)

	return manifest, nil
}

func (dm *YAMLParser) composeInputs(inputs map[string]Parameter, packageInputs PackageInputs, manifestFilePath string) (whisk.KeyValueArr, error) {
	var errorParser error
	keyValArr := make(whisk.KeyValueArr, 0)
	var inputsWithoutValue []string
	var paramsCLI interface{}

	if len(utils.Flags.Param) > 0 {
		paramsCLI, errorParser = utils.GetJSONFromStrings(utils.Flags.Param, false)
		if errorParser != nil {
			return nil, errorParser
		}
	}

	for name, param := range inputs {
		var keyVal whisk.KeyValue
		// keyvalue key is set to parameter name
		keyVal.Key = name
		// parameter on CLI takes the highest precedence such that
		// input variables gets values from CLI first
		if paramsCLI != nil {
			// check if this particular input is specified on CLI
			if v, ok := paramsCLI.(map[string]interface{})[name]; ok {
				keyVal.Value = wskenv.ConvertSingleName(v.(string))
			}
		}
		// if those inputs are not specified on CLI,
		// read their values from the manifest file
		if keyVal.Value == nil {
			keyVal.Value, errorParser = ResolveParameter(name, &param, manifestFilePath)
			if errorParser != nil {
				return nil, errorParser
			}
			if param.Type == STRING && param.Value != nil {
				if keyVal.Value == getTypeDefaultValue(param.Type) {
					if packageInputs.Inputs != nil {
						n := wskenv.GetEnvVarName(param.Value.(string))
						if v, ok := packageInputs.Inputs[n]; ok {
							keyVal.Value = v.Value.(string)
						}
					}
				}
			}
		}
		if keyVal.Value != nil {
			keyValArr = append(keyValArr, keyVal)
		}
		if param.Required && keyVal.Value == getTypeDefaultValue(param.Type) {
			inputsWithoutValue = append(inputsWithoutValue, name)
		}
	}
	if len(inputsWithoutValue) > 0 {
		errMessage := wski18n.T(wski18n.ID_ERR_REQUIRED_INPUTS_MISSING_VALUE_X_inputs_X,
			map[string]interface{}{
				wski18n.KEY_INPUTS: strings.Join(inputsWithoutValue, ", ")})
		return nil, wskderrors.NewYAMLFileFormatError(manifestFilePath, errMessage)
	}

	return keyValArr, nil
}

func (dm *YAMLParser) composeAnnotations(annotations map[string]interface{}) whisk.KeyValueArr {
	listOfAnnotations := make(whisk.KeyValueArr, 0)
	for name, value := range annotations {
		var keyVal whisk.KeyValue
		keyVal.Key = name
		value = wskenv.InterpolateStringWithEnvVar(value)
		keyVal.Value = utils.ConvertInterfaceValue(value)
		listOfAnnotations = append(listOfAnnotations, keyVal)
	}
	return listOfAnnotations
}

func (dm *YAMLParser) ComposeDependenciesFromAllPackages(manifest *YAML, projectPath string, filePath string, managedAnnotations whisk.KeyValue, packageInputs map[string]PackageInputs) (map[string]dependencies.DependencyRecord, error) {
	dependencies := make(map[string]dependencies.DependencyRecord)
	packages := make(map[string]Package)

	if len(manifest.Packages) != 0 {
		packages = manifest.Packages
	} else {
		packages = manifest.GetProject().Packages
	}

	for n, p := range packages {
		d, err := dm.ComposeDependencies(p, projectPath, filePath, n, managedAnnotations, packageInputs[n])
		if err == nil {
			for k, v := range d {
				dependencies[k] = v
			}
		} else {
			return nil, err
		}
	}
	return dependencies, nil
}

func (dm *YAMLParser) ComposeDependencies(pkg Package, projectPath string, filePath string, packageName string, managedAnnotations whisk.KeyValue, packageInputs PackageInputs) (map[string]dependencies.DependencyRecord, error) {

	depMap := make(map[string]dependencies.DependencyRecord)
	for key, dependency := range pkg.Dependencies {
		version := dependency.Version
		if len(version) == 0 {
			version = YAML_VALUE_BRANCH_MASTER
		}

		location := dependency.Location

		isBinding := false
		if dependencies.LocationIsBinding(location) {
			if !strings.HasPrefix(location, PATH_SEPARATOR) {
				location = PATH_SEPARATOR + dependency.Location
			}
			isBinding = true
		} else if dependencies.LocationIsGithub(location) {

			// TODO() define const for the protocol prefix, etc.
			_, err := url.ParseRequestURI(location)
			if err != nil {
				location = HTTPS + dependency.Location
				location = wskenv.InterpolateStringWithEnvVar(location).(string)
			}
			isBinding = false
		} else {
			// TODO() create new named error in wskerrors package
			return nil, errors.New(wski18n.T(wski18n.ID_ERR_DEPENDENCY_UNKNOWN_TYPE))
		}

		inputs, err := dm.composeInputs(dependency.Inputs, packageInputs, filePath)
		if err != nil {
			return nil, err
		}

		annotations := dm.composeAnnotations(dependency.Annotations)

		if utils.Flags.Managed || utils.Flags.Sync {
			annotations = append(annotations, managedAnnotations)
		}

		packDir := path.Join(projectPath, strings.Title(YAML_KEY_PACKAGES))
		depName := packageName + ":" + key
		depMap[depName] = dependencies.NewDependencyRecord(packDir, packageName, location, version, inputs, annotations, isBinding)
	}

	return depMap, nil
}

func (dm *YAMLParser) ComposeAllPackages(projectInputs map[string]Parameter, manifest *YAML, filePath string, managedAnnotations whisk.KeyValue) (map[string]*whisk.Package, map[string]PackageInputs, error) {
	packages := map[string]*whisk.Package{}
	manifestPackages := make(map[string]Package)
	inputs := make(map[string]PackageInputs, 0)

	if len(manifest.Packages) != 0 {
		manifestPackages = manifest.Packages
	} else {
		manifestPackages = manifest.GetProject().Packages
	}

	if len(manifestPackages) == 0 {
		warningString := wski18n.T(
			wski18n.ID_WARN_PACKAGES_NOT_FOUND_X_path_X,
			map[string]interface{}{
				wski18n.KEY_PATH: manifest.Filepath})
		wskprint.PrintOpenWhiskWarning(warningString)
	}

	// Compose each package found in manifest
	for n, p := range manifestPackages {
		s, params, err := dm.ComposePackage(p, n, filePath, managedAnnotations, projectInputs)
		if err != nil {
			return nil, inputs, err
		}
		packages[n] = s
		inputs[n] = PackageInputs{PackageName: n, Inputs: params}
	}

	return packages, inputs, nil
}

func (dm *YAMLParser) composePackageInputs(projectInputs map[string]Parameter, rawInputs map[string]Parameter, filepath string) (map[string]Parameter, whisk.KeyValueArr, error) {
	inputs := make(map[string]Parameter, 0)

	// package inherits all project inputs
	for n, param := range projectInputs {
		inputs[n] = param
	}

	// iterate over package inputs
	for name, i := range rawInputs {
		value, err := ResolveParameter(name, &i, filepath)
		if err != nil {
			return nil, nil, err
		}
		// if value is set to default value for its type,
		// check for input key being an env. variable itself
		if value == getTypeDefaultValue(i.Type) {
			value = wskenv.InterpolateStringWithEnvVar("${" + name + "}")
		}

		// if at this point, still value is set to default value of its type
		// check if input key is defined under Project Inputs
		if value == getTypeDefaultValue(i.Type) {
			if i.Type == STRING && i.Value != nil {
				n := wskenv.GetEnvVarName(i.Value.(string))
				if v, ok := projectInputs[n]; ok {
					value = v.Value.(string)
				}
			}
		}

		// create a Parameter object based on the package inputs
		// resolve the value using env. variables
		// if value is not specified, treat input key as an env. variable
		// check if input key is defined in environment
		// else set it to its default value based on the type for now
		// the input value will be updated if its specified in deployment
		// or on CLI using --param or --param-file
		i.Value = value
		inputs[name] = i
	}

	// create an array of Key/Value pair with inputs
	// inputs name as key and with its value if its not nil
	keyValArr := make(whisk.KeyValueArr, 0)
	for name, param := range inputs {
		var keyVal whisk.KeyValue
		keyVal.Key = name
		keyVal.Value = param.Value
		if keyVal.Value != nil {
			keyValArr = append(keyValArr, keyVal)
		}
	}

	return inputs, keyValArr, nil
}

func (dm *YAMLParser) ComposePackage(pkg Package, packageName string, filePath string, managedAnnotations whisk.KeyValue, projectInputs map[string]Parameter) (*whisk.Package, map[string]Parameter, error) {
	pag := &whisk.Package{}
	pag.Name = packageName
	//The namespace for this package is absent, so we use default guest here.
	pag.Namespace = pkg.Namespace
	pub := false
	pag.Publish = &pub

	//Version is a mandatory value
	//If it is an empty string, it will be set to default value
	//And print an warning message
	// TODO(#673) implement STRICT flag
	if pkg.Version == "" {
		warningString := wski18n.T(
			wski18n.ID_WARN_KEY_MISSING_X_key_X_value_X,
			map[string]interface{}{
				wski18n.KEY_KEY:   wski18n.PACKAGE_VERSION,
				wski18n.KEY_VALUE: DEFAULT_PACKAGE_VERSION})
		wskprint.PrintOpenWhiskWarning(warningString)

		warningString = wski18n.T(
			wski18n.ID_WARN_KEYVALUE_NOT_SAVED_X_key_X,
			map[string]interface{}{wski18n.KEY_KEY: wski18n.PACKAGE_VERSION})

		wskprint.PrintOpenWhiskWarning(warningString)
		pkg.Version = DEFAULT_PACKAGE_VERSION
	}

	//License is a mandatory value
	//set license to unknown if it is an empty string
	//And print an warning message
	// TODO(#673) implement STRICT flag
	if pkg.License == "" {
		warningString := wski18n.T(
			wski18n.ID_WARN_KEY_MISSING_X_key_X_value_X,
			map[string]interface{}{
				wski18n.KEY_KEY:   wski18n.PACKAGE_LICENSE,
				wski18n.KEY_VALUE: DEFAULT_PACKAGE_LICENSE})
		wskprint.PrintOpenWhiskWarning(warningString)

		warningString = wski18n.T(
			wski18n.ID_WARN_KEYVALUE_NOT_SAVED_X_key_X,
			map[string]interface{}{wski18n.KEY_KEY: wski18n.PACKAGE_VERSION})

		wskprint.PrintOpenWhiskWarning(warningString)

		pkg.License = DEFAULT_PACKAGE_LICENSE
	} else {
		utils.CheckLicense(pkg.License)
	}

	// package inputs are set as package inputs of type Parameter{}
	// read all package inputs, interpolate their values using env. variables
	// check if input variable itself is an env. variable
	packageInputs, inputs, err := dm.composePackageInputs(projectInputs, pkg.Inputs, filePath)
	if err != nil {
		return nil, nil, err
	}
	if len(inputs) > 0 {
		pag.Parameters = inputs
	}

	// set Package Annotations
	listOfAnnotations := dm.composeAnnotations(pkg.Annotations)
	if len(listOfAnnotations) > 0 {
		pag.Annotations = append(pag.Annotations, listOfAnnotations...)
	}

	// add Managed Annotations if this is Managed Deployment
	if utils.Flags.Managed || utils.Flags.Sync {
		pag.Annotations = append(pag.Annotations, managedAnnotations)
	}

	// "default" package is a reserved package name
	// and in this case wskdeploy deploys openwhisk entities under
	// /namespace instead of /namespace/package
	if strings.ToLower(pag.Name) == DEFAULT_PACKAGE {
		wskprint.PrintlnOpenWhiskInfo(wski18n.T(wski18n.ID_MSG_DEFAULT_PACKAGE))
		// when a package is marked public with "Public: true" in manifest file
		// the package is visible to anyone and created with publish state
		// set to shared otherwise publish state is set to private
	} else if pkg.Public {
		warningMsg := wski18n.T(wski18n.ID_WARN_PACKAGE_IS_PUBLIC_X_package_X,
			map[string]interface{}{
				wski18n.KEY_PACKAGE: pag.Name})
		wskprint.PrintlnOpenWhiskWarning(warningMsg)
		pag.Publish = &(pkg.Public)
	}

	return pag, packageInputs, nil
}

func (dm *YAMLParser) ComposeSequencesFromAllPackages(namespace string, mani *YAML, manifestFilePath string, managedAnnotations whisk.KeyValue, packageInputs map[string]PackageInputs) ([]utils.ActionRecord, error) {
	var sequences []utils.ActionRecord = make([]utils.ActionRecord, 0)
	manifestPackages := make(map[string]Package)

	if len(mani.Packages) != 0 {
		manifestPackages = mani.Packages
	} else {
		manifestPackages = mani.GetProject().Packages
	}

	for n, p := range manifestPackages {
		s, err := dm.ComposeSequences(namespace, p.Sequences, n, manifestFilePath, managedAnnotations, packageInputs[n])
		if err == nil {
			sequences = append(sequences, s...)
		} else {
			return nil, err
		}
	}
	return sequences, nil
}

func (dm *YAMLParser) ComposeSequences(namespace string, sequences map[string]Sequence, packageName string, manifestFilePath string, managedAnnotations whisk.KeyValue, packageInputs PackageInputs) ([]utils.ActionRecord, error) {
	var listOfSequences []utils.ActionRecord = make([]utils.ActionRecord, 0)
	var errorParser error

	for key, sequence := range sequences {
		wskaction := new(whisk.Action)
		wskaction.Exec = new(whisk.Exec)
		wskaction.Exec.Kind = YAML_KEY_SEQUENCE
		actionList := strings.Split(sequence.Actions, ",")

		var components []string
		for _, a := range actionList {
			act := strings.TrimSpace(a)
			if !strings.ContainsRune(act, []rune(PATH_SEPARATOR)[0]) && !strings.HasPrefix(act, packageName+PATH_SEPARATOR) &&
				strings.ToLower(packageName) != DEFAULT_PACKAGE {
				act = path.Join(packageName, act)
			}
			components = append(components, path.Join(PATH_SEPARATOR+namespace, act))
		}

		wskaction.Exec.Components = components
		if i, ok := packageInputs.Inputs[wskenv.GetEnvVarName(key)]; ok {
			wskaction.Name = i.Value.(string)
		} else {
			wskaction.Name = wskenv.ConvertSingleName(key)
		}
		pub := false
		wskaction.Publish = &pub
		wskaction.Namespace = namespace

		annotations := dm.composeAnnotations(sequence.Annotations)
		if len(annotations) > 0 {
			wskaction.Annotations = annotations
		}

		// appending managed annotations if its a managed deployment
		if utils.Flags.Managed || utils.Flags.Sync {
			wskaction.Annotations = append(wskaction.Annotations, managedAnnotations)
		}

		// Web Export
		// Treat sequence as a web action, a raw HTTP web action, or as a standard action based on web-export;
		// when web-export is set to yes | true, treat sequence as a web action,
		// when web-export is set to raw, treat sequence as a raw HTTP web action,
		// when web-export is set to no | false, treat sequence as a standard action
		if len(sequence.Web) != 0 {
			wskaction.Annotations, errorParser = webaction.WebAction(manifestFilePath, wskaction.Name, sequence.Web, wskaction.Annotations, false)
			if errorParser != nil {
				return nil, errorParser
			}
		}

		record := utils.ActionRecord{Action: wskaction, Packagename: packageName, Filepath: key}
		listOfSequences = append(listOfSequences, record)
	}
	return listOfSequences, nil
}

func (dm *YAMLParser) ComposeActionsFromAllPackages(manifest *YAML, filePath string, managedAnnotations whisk.KeyValue, packageInputs map[string]PackageInputs) ([]utils.ActionRecord, error) {
	var actions []utils.ActionRecord = make([]utils.ActionRecord, 0)
	manifestPackages := make(map[string]Package)

	if len(manifest.Packages) != 0 {
		manifestPackages = manifest.Packages
	} else {
		manifestPackages = manifest.GetProject().Packages
	}

	for n, p := range manifestPackages {
		a, err := dm.ComposeActions(filePath, p.Actions, n, managedAnnotations, packageInputs[n])
		if err == nil {
			actions = append(actions, a...)
		} else {
			return nil, err
		}
	}
	return actions, nil
}

func (dm *YAMLParser) validateActionCode(manifestFilePath string, action Action) error {
	// Check if action.Function is specified with action.Code
	// with action.Code, action.Function is not allowed
	// with action.Code, action.Runtime should be specified
	if len(action.Function) != 0 {
		err := wski18n.T(wski18n.ID_ERR_ACTION_INVALID_X_action_X,
			map[string]interface{}{
				wski18n.KEY_ACTION: action.Name})
		return wskderrors.NewYAMLFileFormatError(manifestFilePath, err)
	}
	if len(action.Runtime) == 0 {
		err := wski18n.T(wski18n.ID_ERR_ACTION_MISSING_RUNTIME_WITH_CODE_X_action_X,
			map[string]interface{}{
				wski18n.KEY_ACTION: action.Name})
		return wskderrors.NewYAMLFileFormatError(manifestFilePath, err)
	}
	return nil
}

func (dm *YAMLParser) readActionCode(manifestFilePath string, action Action) (*whisk.Exec, error) {
	exec := new(whisk.Exec)
	if err := dm.validateActionCode(manifestFilePath, action); err != nil {
		return nil, err
	}
	// validate runtime from the manifest file
	// error out if the specified runtime is not valid or not supported
	// even if runtime is invalid, deploy action with specified runtime in strict mode
	if utils.Flags.Strict {
		exec.Kind = action.Runtime
	} else if runtimes.CheckExistRuntime(action.Runtime, runtimes.SupportedRunTimes) {
		exec.Kind = action.Runtime
	} else if len(runtimes.DefaultRunTimes[action.Runtime]) != 0 {
		exec.Kind = runtimes.DefaultRunTimes[action.Runtime]
	} else {
		err := wski18n.T(wski18n.ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X,
			map[string]interface{}{
				wski18n.KEY_RUNTIME: action.Runtime,
				wski18n.KEY_ACTION:  action.Name})
		return nil, wskderrors.NewYAMLFileFormatError(manifestFilePath, err)
	}
	exec.Code = &(action.Code)
	// we can specify the name of the action entry point using main
	if len(action.Main) != 0 {
		exec.Main = action.Main
	}
	return exec, nil
}

func (dm *YAMLParser) validateActionFunction(manifestFileName string, action Action, ext string, kind string) error {
	// produce an error when a runtime could not be derived from the action file extension
	// and its not explicitly specified in the manifest YAML file
	// and action source is not a zip file
	if len(action.Runtime) == 0 && len(action.Docker) == 0 && !action.Native {
		if ext == runtimes.ZIP_FILE_EXTENSION {
			errMessage := wski18n.T(wski18n.ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X,
				map[string]interface{}{
					wski18n.KEY_RUNTIME: runtimes.RUNTIME_NOT_SPECIFIED,
					wski18n.KEY_ACTION:  action.Name})
			return wskderrors.NewInvalidRuntimeError(errMessage,
				manifestFileName,
				action.Name,
				runtimes.RUNTIME_NOT_SPECIFIED,
				runtimes.ListOfSupportedRuntimes(runtimes.SupportedRunTimes))
		} else if len(kind) == 0 {
			errMessage := wski18n.T(wski18n.ID_ERR_RUNTIME_ACTION_SOURCE_NOT_SUPPORTED_X_ext_X_action_X,
				map[string]interface{}{
					wski18n.KEY_EXTENSION: ext,
					wski18n.KEY_ACTION:    action.Name})
			return wskderrors.NewInvalidRuntimeError(errMessage,
				manifestFileName,
				action.Name,
				runtimes.RUNTIME_NOT_SPECIFIED,
				runtimes.ListOfSupportedRuntimes(runtimes.SupportedRunTimes))
		}
	}
	return nil
}

func (dm *YAMLParser) readActionFunction(manifestFilePath string, manifestFileName string, action Action) (string, *whisk.Exec, error) {
	var actionFilePath string
	var zipFileName string
	exec := new(whisk.Exec)
	f := wskenv.InterpolateStringWithEnvVar(action.Function)
	interpolatedActionFunction := f.(string)

	// check if action function is pointing to an URL
	// we do not support if function is pointing to remote directory
	// therefore error out if there is a combination of http/https ending in a directory
	if strings.HasPrefix(interpolatedActionFunction, HTTP) || strings.HasPrefix(interpolatedActionFunction, HTTPS) {
		if len(path.Ext(interpolatedActionFunction)) == 0 {
			err := wski18n.T(wski18n.ID_ERR_ACTION_FUNCTION_REMOTE_DIR_NOT_SUPPORTED_X_action_X_url_X,
				map[string]interface{}{
					wski18n.KEY_ACTION: action.Name,
					wski18n.KEY_URL:    interpolatedActionFunction})
			return actionFilePath, nil, wskderrors.NewYAMLFileFormatError(manifestFilePath, err)
		}
		actionFilePath = interpolatedActionFunction
	} else {
		actionFilePath = strings.TrimRight(manifestFilePath, manifestFileName) + interpolatedActionFunction
	}

	if utils.IsDirectory(actionFilePath) {
		zipFileName = actionFilePath + "." + runtimes.ZIP_FILE_EXTENSION
		err := utils.NewZipWritter(actionFilePath, zipFileName, action.Include, action.Exclude, filepath.Dir(manifestFilePath)).Zip()
		if err != nil {
			return actionFilePath, nil, err
		}
		defer os.Remove(zipFileName)
		actionFilePath = zipFileName
	}

	action.Function = actionFilePath

	// determine extension of the given action source file
	ext := filepath.Ext(actionFilePath)
	// drop the "." from file extension
	if len(ext) > 0 && ext[0] == '.' {
		ext = ext[1:]
	}

	// determine default runtime for the given file extension
	var kind string
	r := runtimes.FileExtensionRuntimeKindMap[ext]
	kind = runtimes.DefaultRunTimes[r]
	if err := dm.validateActionFunction(manifestFileName, action, ext, kind); err != nil {
		return actionFilePath, nil, err
	}
	exec.Kind = kind

	dat, err := utils.Read(actionFilePath)
	if err != nil {
		return actionFilePath, nil, err
	}
	code := string(dat)
	if ext == runtimes.ZIP_FILE_EXTENSION || ext == runtimes.JAR_FILE_EXTENSION {
		code = base64.StdEncoding.EncodeToString([]byte(dat))
	}
	exec.Code = &code

	/*
	*  Action.Runtime
	*  Perform few checks if action runtime is specified in manifest YAML file
	*  (1) Check if specified runtime is one of the supported runtimes by OpenWhisk server
	*  (2) Check if specified runtime is consistent with action source file extensions
	*  Set the action runtime to match with the source file extension, if wskdeploy is not invoked in strict mode
	 */
	if len(action.Runtime) != 0 {
		if runtimes.CheckExistRuntime(action.Runtime, runtimes.SupportedRunTimes) {
			// for zip actions, rely on the runtimes from the manifest file as it can not be derived from the action source file extension
			// pick runtime from manifest file if its supported by OpenWhisk server
			if ext == runtimes.ZIP_FILE_EXTENSION {
				exec.Kind = action.Runtime
			} else {
				if runtimes.CheckRuntimeConsistencyWithFileExtension(ext, action.Runtime) {
					exec.Kind = action.Runtime
				} else {
					warnStr := wski18n.T(wski18n.ID_ERR_RUNTIME_MISMATCH_X_runtime_X_ext_X_action_X,
						map[string]interface{}{
							wski18n.KEY_RUNTIME:   action.Runtime,
							wski18n.KEY_EXTENSION: ext,
							wski18n.KEY_ACTION:    action.Name})
					wskprint.PrintOpenWhiskWarning(warnStr)

					// even if runtime is not consistent with file extension, deploy action with specified runtime in strict mode
					if utils.Flags.Strict {
						exec.Kind = action.Runtime
					} else {
						warnStr := wski18n.T(wski18n.ID_WARN_RUNTIME_CHANGED_X_runtime_X_action_X,
							map[string]interface{}{
								wski18n.KEY_RUNTIME: exec.Kind,
								wski18n.KEY_ACTION:  action.Name})
						wskprint.PrintOpenWhiskWarning(warnStr)
					}
				}
			}
		} else {
			warnStr := wski18n.T(wski18n.ID_ERR_RUNTIME_INVALID_X_runtime_X_action_X,
				map[string]interface{}{
					wski18n.KEY_RUNTIME: action.Runtime,
					wski18n.KEY_ACTION:  action.Name})
			wskprint.PrintOpenWhiskWarning(warnStr)

			if ext == runtimes.ZIP_FILE_EXTENSION {
				// for zip action, error out if specified runtime is not supported by
				// OpenWhisk server
				return actionFilePath, nil, wskderrors.NewInvalidRuntimeError(warnStr,
					manifestFileName,
					action.Name,
					action.Runtime,
					runtimes.ListOfSupportedRuntimes(runtimes.SupportedRunTimes))
			} else {
				if utils.Flags.Strict {
					exec.Kind = action.Runtime
				} else {
					warnStr := wski18n.T(wski18n.ID_WARN_RUNTIME_CHANGED_X_runtime_X_action_X,
						map[string]interface{}{
							wski18n.KEY_RUNTIME: exec.Kind,
							wski18n.KEY_ACTION:  action.Name})
					wskprint.PrintOpenWhiskWarning(warnStr)
				}
			}

		}
	}
	// we can specify the name of the action entry point using main
	if len(action.Main) != 0 {
		exec.Main = action.Main
	}

	return actionFilePath, exec, nil
}

func (dm *YAMLParser) composeActionExec(manifestFilePath string, manifestFileName string, action Action) (string, *whisk.Exec, error) {
	var actionFilePath string
	exec := new(whisk.Exec)
	var err error

	if len(action.Code) != 0 {
		exec, err = dm.readActionCode(manifestFilePath, action)
		if err != nil {
			return actionFilePath, nil, err
		}
	}
	if len(action.Function) != 0 {
		actionFilePath, exec, err = dm.readActionFunction(manifestFilePath, manifestFileName, action)
		if err != nil {
			return actionFilePath, nil, err
		}
	}

	// when an action has Docker image specified,
	// set exec.Kind to "blackbox" and
	// set exec.Image to specified image e.g. dockerhub/image
	// when an action Native is set to true,
	// set exec.Image to openwhisk/skeleton
	if len(action.Docker) != 0 || action.Native {
		exec.Kind = runtimes.BLACKBOX
		if action.Native {
			exec.Image = NATIVE_DOCKER_IMAGE
		} else {
			exec.Image = action.Docker
		}
	}

	return actionFilePath, exec, err
}

func (dm *YAMLParser) validateActionLimits(limits Limits) {
	// TODO() use LIMITS_UNSUPPORTED in yamlparser to enumerate through instead of hardcoding
	// emit warning errors if these limits are not nil
	utils.NotSupportLimits(limits.ConcurrentActivations, LIMIT_VALUE_CONCURRENT_ACTIVATIONS)
	utils.NotSupportLimits(limits.UserInvocationRate, LIMIT_VALUE_USER_INVOCATION_RATE)
	utils.NotSupportLimits(limits.CodeSize, LIMIT_VALUE_CODE_SIZE)
	utils.NotSupportLimits(limits.ParameterSize, LIMIT_VALUE_PARAMETER_SIZE)
}

func (dm *YAMLParser) composeActionLimits(limits Limits) *whisk.Limits {
	dm.validateActionLimits(limits)
	wsklimits := new(whisk.Limits)
	for _, t := range LIMITS_SUPPORTED {
		switch t {
		case LIMIT_VALUE_TIMEOUT:
			if utils.LimitsTimeoutValidation(limits.Timeout) {
				wsklimits.Timeout = limits.Timeout
			} else {
				warningString := wski18n.T(wski18n.ID_WARN_LIMIT_IGNORED_X_limit_X,
					map[string]interface{}{wski18n.KEY_LIMIT: LIMIT_VALUE_TIMEOUT})
				wskprint.PrintOpenWhiskWarning(warningString)
			}
		case LIMIT_VALUE_MEMORY_SIZE:
			if utils.LimitsMemoryValidation(limits.Memory) {
				wsklimits.Memory = limits.Memory
			} else {
				warningString := wski18n.T(wski18n.ID_WARN_LIMIT_IGNORED_X_limit_X,
					map[string]interface{}{wski18n.KEY_LIMIT: LIMIT_VALUE_MEMORY_SIZE})
				wskprint.PrintOpenWhiskWarning(warningString)

			}
		case LIMIT_VALUE_LOG_SIZE:
			if utils.LimitsLogsizeValidation(limits.Logsize) {
				wsklimits.Logsize = limits.Logsize
			} else {
				warningString := wski18n.T(wski18n.ID_WARN_LIMIT_IGNORED_X_limit_X,
					map[string]interface{}{wski18n.KEY_LIMIT: LIMIT_VALUE_LOG_SIZE})
				wskprint.PrintOpenWhiskWarning(warningString)

			}
		}
	}
	if wsklimits.Timeout != nil || wsklimits.Memory != nil || wsklimits.Logsize != nil {
		return wsklimits
	}
	return nil
}

func (dm *YAMLParser) validateActionWebFlag(action Action) {
	if len(action.Web) != 0 && len(action.Webexport) != 0 {
		warningString := wski18n.T(wski18n.ID_WARN_ACTION_WEB_X_action_X,
			map[string]interface{}{wski18n.KEY_ACTION: action.Name})
		wskprint.PrintOpenWhiskWarning(warningString)
	}
}

func (dm *YAMLParser) ComposeActions(manifestFilePath string, actions map[string]Action, packageName string, managedAnnotations whisk.KeyValue, packageInputs PackageInputs) ([]utils.ActionRecord, error) {

	var errorParser error
	var listOfActions []utils.ActionRecord = make([]utils.ActionRecord, 0)
	splitManifestFilePath := strings.Split(manifestFilePath, string(PATH_SEPARATOR))
	manifestFileName := splitManifestFilePath[len(splitManifestFilePath)-1]

	for actionName, action := range actions {
		var actionFilePath string

		// update the action (of type Action) to set its name
		// here key name is the action name
		action.Name = actionName

		// Create action data object from client library
		wskaction := new(whisk.Action)

		//set action.Function to action.Location
		//because Location is deprecated in Action entity
		if len(action.Function) == 0 && len(action.Location) != 0 {
			action.Function = action.Location
		}

		actionFilePath, wskaction.Exec, errorParser = dm.composeActionExec(manifestFilePath, manifestFileName, action)
		if errorParser != nil {
			return nil, errorParser
		}

		// Action.Inputs
		listOfInputs, err := dm.composeInputs(action.Inputs, packageInputs, manifestFilePath)
		if err != nil {
			return nil, err
		}
		if len(listOfInputs) > 0 {
			wskaction.Parameters = listOfInputs
		}

		// Action.Outputs
		// TODO{} add outputs as annotations (work to discuss officially supporting for compositions)
		//listOfOutputs, err := dm.composeOutputs(action.Outputs, manifestFilePath)
		//if err != nil {
		//	return nil, err
		//}
		//if len(listOfOutputs) > 0 {
		//	wskaction.Annotations = listOfOutputs
		//}

		// Action.Annotations
		if listOfAnnotations := dm.composeAnnotations(action.Annotations); len(listOfAnnotations) > 0 {
			wskaction.Annotations = append(wskaction.Annotations, listOfAnnotations...)
		}

		// add managed annotations if its marked as managed deployment
		if utils.Flags.Managed || utils.Flags.Sync {
			wskaction.Annotations = append(wskaction.Annotations, managedAnnotations)
		}

		// Web Export
		// Treat ACTION as a web action, a raw HTTP web action, or as a standard action based on web-export;
		// when web-export is set to yes | true, treat action as a web action,
		// when web-export is set to raw, treat action as a raw HTTP web action,
		// when web-export is set to no | false, treat action as a standard action
		dm.validateActionWebFlag(action)
		if len(action.GetWeb()) != 0 {
			wskaction.Annotations, errorParser = webaction.WebAction(manifestFilePath, action.Name, action.GetWeb(), wskaction.Annotations, false)
			if errorParser != nil {
				return listOfActions, errorParser
			}
		}

		// Action.Limits
		if action.Limits != nil {
			if wsklimits := dm.composeActionLimits(*(action.Limits)); wsklimits != nil {
				wskaction.Limits = wsklimits
			}
		}
		// Conductor Action
		if action.Conductor {
			wskaction.Annotations = append(wskaction.Annotations, conductor.ConductorAction())
		}

		wskaction.Name = actionName
		pub := false
		wskaction.Publish = &pub

		record := utils.ActionRecord{Action: wskaction, Packagename: packageName, Filepath: actionFilePath}
		listOfActions = append(listOfActions, record)
	}

	return listOfActions, nil

}

func (dm *YAMLParser) ComposeTriggersFromAllPackages(manifest *YAML, filePath string, managedAnnotations whisk.KeyValue, inputs map[string]PackageInputs) ([]*whisk.Trigger, error) {
	var triggers []*whisk.Trigger = make([]*whisk.Trigger, 0)
	manifestPackages := make(map[string]Package)

	if len(manifest.Packages) != 0 {
		manifestPackages = manifest.Packages
	} else {
		manifestPackages = manifest.GetProject().Packages
	}

	for packageName, pkg := range manifestPackages {
		t, err := dm.ComposeTriggers(filePath, pkg, managedAnnotations, inputs[packageName])
		if err == nil {
			triggers = append(triggers, t...)
		} else {
			return nil, err
		}
	}
	return triggers, nil
}

func (dm *YAMLParser) ComposeTriggers(filePath string, pkg Package, managedAnnotations whisk.KeyValue, packageInputs PackageInputs) ([]*whisk.Trigger, error) {
	var errorParser error
	var listOfTriggers []*whisk.Trigger = make([]*whisk.Trigger, 0)

	for _, trigger := range pkg.GetTriggerList() {
		wsktrigger := new(whisk.Trigger)
		if i, ok := packageInputs.Inputs[wskenv.GetEnvVarName(trigger.Name)]; ok {
			wsktrigger.Name = i.Value.(string)
		} else {
			wsktrigger.Name = wskenv.ConvertSingleName(trigger.Name)
		}
		wsktrigger.Namespace = trigger.Namespace
		pub := false
		wsktrigger.Publish = &pub

		// print warning information when .Source key's value is not empty
		if len(trigger.Source) != 0 {
			warningString := wski18n.T(
				wski18n.ID_WARN_KEY_DEPRECATED_X_oldkey_X_filetype_X_newkey_X,
				map[string]interface{}{
					wski18n.KEY_OLD:       YAML_KEY_SOURCE,
					wski18n.KEY_NEW:       YAML_KEY_FEED,
					wski18n.KEY_FILE_TYPE: wski18n.MANIFEST_FILE})
			wskprint.PrintOpenWhiskWarning(warningString)
		}
		if len(trigger.Feed) == 0 {
			trigger.Feed = trigger.Source
		}

		// replacing env. variables here in the trigger feed name
		// to support trigger feed with $READ_FROM_ENV_TRIGGER_FEED
		trigger.Feed = wskenv.ConvertSingleName(trigger.Feed)

		keyValArr := make(whisk.KeyValueArr, 0)
		if len(trigger.Feed) != 0 {
			var keyVal whisk.KeyValue
			keyVal.Key = YAML_KEY_FEED
			keyVal.Value = trigger.Feed
			keyValArr = append(keyValArr, keyVal)
			wsktrigger.Annotations = keyValArr
		}

		inputs, err := dm.composeInputs(trigger.Inputs, packageInputs, filePath)
		if err != nil {
			return nil, errorParser
		}
		if len(inputs) > 0 {
			wsktrigger.Parameters = inputs
		}

		listOfAnnotations := dm.composeAnnotations(trigger.Annotations)
		if len(listOfAnnotations) > 0 {
			wsktrigger.Annotations = append(wsktrigger.Annotations, listOfAnnotations...)
		}

		// add managed annotations if its a managed deployment
		if utils.Flags.Managed || utils.Flags.Sync {
			wsktrigger.Annotations = append(wsktrigger.Annotations, managedAnnotations)
		}

		listOfTriggers = append(listOfTriggers, wsktrigger)
	}
	return listOfTriggers, nil
}

func (dm *YAMLParser) ComposeRulesFromAllPackages(manifest *YAML, managedAnnotations whisk.KeyValue, packageInputs map[string]PackageInputs) ([]*whisk.Rule, error) {
	var rules []*whisk.Rule = make([]*whisk.Rule, 0)
	manifestPackages := make(map[string]Package)

	if len(manifest.Packages) != 0 {
		manifestPackages = manifest.Packages
	} else {
		manifestPackages = manifest.GetProject().Packages
	}

	for n, p := range manifestPackages {
		r, err := dm.ComposeRules(p, n, managedAnnotations, packageInputs[n])
		if err == nil {
			rules = append(rules, r...)
		} else {
			return nil, err
		}
	}
	return rules, nil
}

func (dm *YAMLParser) ComposeRules(pkg Package, packageName string, managedAnnotations whisk.KeyValue, packageInputs PackageInputs) ([]*whisk.Rule, error) {
	var rules []*whisk.Rule = make([]*whisk.Rule, 0)

	for _, rule := range pkg.GetRuleList() {
		wskrule := new(whisk.Rule)
		if i, ok := packageInputs.Inputs[wskenv.GetEnvVarName(rule.Name)]; ok {
			wskrule.Name = i.Value.(string)
		} else {
			wskrule.Name = wskenv.ConvertSingleName(rule.Name)
		}
		//wskrule.Namespace = rule.Namespace
		pub := false
		wskrule.Publish = &pub
		if i, ok := packageInputs.Inputs[wskenv.GetEnvVarName(rule.Trigger)]; ok {
			wskrule.Trigger = i.Value.(string)
		} else {
			wskrule.Trigger = wskenv.ConvertSingleName(rule.Trigger)
		}
		if i, ok := packageInputs.Inputs[wskenv.GetEnvVarName(rule.Action)]; ok {
			wskrule.Action = i.Value.(string)
		} else {
			wskrule.Action = wskenv.ConvertSingleName(rule.Action)
		}
		act := strings.TrimSpace(wskrule.Action.(string))
		if !strings.ContainsRune(act, []rune(PATH_SEPARATOR)[0]) && !strings.HasPrefix(act, packageName+PATH_SEPARATOR) &&
			strings.ToLower(packageName) != DEFAULT_PACKAGE {
			act = path.Join(packageName, act)
		}
		wskrule.Action = act
		listOfAnnotations := dm.composeAnnotations(rule.Annotations)
		if len(listOfAnnotations) > 0 {
			wskrule.Annotations = append(wskrule.Annotations, listOfAnnotations...)
		}

		// add managed annotations if its a managed deployment
		if utils.Flags.Managed || utils.Flags.Sync {
			wskrule.Annotations = append(wskrule.Annotations, managedAnnotations)
		}

		rules = append(rules, wskrule)
	}
	return rules, nil
}

func (dm *YAMLParser) ComposeApiRecordsFromAllPackages(client *whisk.Config, manifest *YAML) ([]*whisk.ApiCreateRequest, map[string]*whisk.ApiCreateRequestOptions, error) {
	var requests = make([]*whisk.ApiCreateRequest, 0)
	var responses = make(map[string]*whisk.ApiCreateRequestOptions, 0)
	manifestPackages := make(map[string]Package)

	if len(manifest.Packages) != 0 {
		manifestPackages = manifest.Packages
	} else {
		manifestPackages = manifest.GetProject().Packages
	}

	for packageName, p := range manifestPackages {
		r, response, err := dm.ComposeApiRecords(client, packageName, p, manifest.Filepath)
		if err == nil {
			requests = append(requests, r...)
			for k, v := range response {
				responses[k] = v
			}
		} else {
			return nil, nil, err
		}
	}
	return requests, responses, nil
}

/*
 * read API section from manifest file:
 * apis: # List of APIs
 * 		hello-world: #API name
 *			/hello: #gateway base path
 *	    		/world:   #gateway rel path
 *					greeting: get #action name: gateway method
 *
 * compose APIDoc structure from the manifest:
 * {
 *	"apidoc":{
 *      	"namespace":<namespace>,
 *      	"gatewayBasePath":"/hello",
 *      	"gatewayPath":"/world",
 *      	"gatewayMethod":"GET",
 *      	"action":{
 *         		"name":"hello",
 *			"namespace":"guest",
 *			"backendMethod":"GET",
 *			"backendUrl":<url>,
 *			"authkey":<auth>
 *		}
 * 	}
 * }
 */
func (dm *YAMLParser) ComposeApiRecords(client *whisk.Config, packageName string, pkg Package, manifestPath string) ([]*whisk.ApiCreateRequest, map[string]*whisk.ApiCreateRequestOptions, error) {
	var requests = make([]*whisk.ApiCreateRequest, 0)

	// verify APIGW_ACCESS_TOKEN is set before composing APIs
	// until this point, we dont know whether APIs are specified in manifest or not
	if pkg.Apis != nil && len(pkg.Apis) != 0 {
		if len(client.ApigwAccessToken) == 0 {
			return nil, nil, wskderrors.NewWhiskClientInvalidConfigError(
				wski18n.ID_MSG_CONFIG_MISSING_APIGW_ACCESS_TOKEN)
		}
	}

	requestOptions := make(map[string]*whisk.ApiCreateRequestOptions, 0)

	for apiName, apiDoc := range pkg.Apis {
		for gatewayBasePath, gatewayBasePathMap := range apiDoc {
			// Base Path
			// validate base path should not have any path parameters
			if !isGatewayBasePathValid(gatewayBasePath) {
				err := wskderrors.NewYAMLParserErr(manifestPath,
					wski18n.T(wski18n.ID_ERR_API_GATEWAY_BASE_PATH_INVALID_X_api_X,
						map[string]interface{}{wski18n.KEY_API_BASE_PATH: gatewayBasePath}))
				return requests, requestOptions, err
			}
			// append "/" to the gateway base path if its missing
			if !strings.HasPrefix(gatewayBasePath, PATH_SEPARATOR) {
				gatewayBasePath = PATH_SEPARATOR + gatewayBasePath
			}
			for gatewayRelPath, gatewayRelPathMap := range gatewayBasePathMap {
				// Relative Path
				// append "/" to the gateway relative path if its missing
				if !strings.HasPrefix(gatewayRelPath, PATH_SEPARATOR) {
					gatewayRelPath = PATH_SEPARATOR + gatewayRelPath
				}
				for actionName, gatewayMethodResponse := range gatewayRelPathMap {
					// verify that the action is defined under actions sections
					if _, ok := pkg.Actions[actionName]; ok {
						// verify that the action is defined as web action
						// web or web-export set to any of [true, yes, raw]
						a := pkg.Actions[actionName]
						if !webaction.IsWebAction(a.GetWeb()) {
							warningString := wski18n.T(wski18n.ID_WARN_API_MISSING_WEB_ACTION_X_action_X_api_X,
								map[string]interface{}{
									wski18n.KEY_ACTION: actionName,
									wski18n.KEY_API:    apiName})
							wskprint.PrintOpenWhiskWarning(warningString)
							if a.Annotations == nil {
								a.Annotations = make(map[string]interface{}, 0)
							}
							a.Annotations[webaction.WEB_EXPORT_ANNOT] = true
							pkg.Actions[actionName] = a
						}
						// verify that the sequence is defined under sequences sections
					} else if _, ok := pkg.Sequences[actionName]; ok {
						// verify that the sequence is defined as web sequence
						// web set to any of [true, yes, raw]
						a := pkg.Sequences[actionName]
						if !webaction.IsWebSequence(a.Web) {
							warningString := wski18n.T(wski18n.ID_WARN_API_MISSING_WEB_SEQUENCE_X_sequence_X_api_X,
								map[string]interface{}{
									wski18n.KEY_SEQUENCE: actionName,
									wski18n.KEY_API:      apiName})
							wskprint.PrintOpenWhiskWarning(warningString)
							if a.Annotations == nil {
								a.Annotations = make(map[string]interface{}, 0)
							}
							a.Annotations[webaction.WEB_EXPORT_ANNOT] = true
							pkg.Sequences[actionName] = a
						}
						// return failure since action or sequence are not defined in the manifest
					} else {
						return nil, nil, wskderrors.NewYAMLFileFormatError(manifestPath,
							wski18n.T(wski18n.ID_ERR_API_MISSING_ACTION_OR_SEQUENCE_X_action_or_sequence_X_api_X,
								map[string]interface{}{
									wski18n.KEY_ACTION: actionName,
									wski18n.KEY_API:    apiName}))
					}

					// get the list of path parameters from relative path
					pathParameters := generatePathParameters(gatewayRelPath)

					// Check if response type is set to http for API using path parameters
					if strings.ToLower(gatewayMethodResponse.Method) != utils.HTTP_FILE_EXTENSION &&
						len(pathParameters) > 0 {
						warningString := wski18n.T(wski18n.ID_WARN_API_INVALID_RESPONSE_TYPE,
							map[string]interface{}{
								wski18n.KEY_API:               apiName,
								wski18n.KEY_API_RELATIVE_PATH: gatewayRelPath,
								wski18n.KEY_RESPONSE:          gatewayMethodResponse.Response})
						wskprint.PrintlnOpenWhiskWarning(warningString)
						gatewayMethodResponse.Response = utils.HTTP_FILE_EXTENSION
					}

					// Chekc if API verb is valid, it must be one of (GET, PUT, POST, DELETE)
					if _, ok := whisk.ApiVerbs[strings.ToUpper(gatewayMethodResponse.Method)]; !ok {
						return nil, nil, wskderrors.NewInvalidAPIGatewayMethodError(manifestPath,
							gatewayBasePath+gatewayRelPath,
							gatewayMethodResponse.Method,
							dm.getGatewayMethods())
					}

					apiDocActionName := actionName
					if strings.ToLower(packageName) != DEFAULT_PACKAGE {
						apiDocActionName = packageName + PATH_SEPARATOR + actionName
					}

					// set action of an API Doc
					apiDocAction := whisk.ApiAction{
						Name:      apiDocActionName,
						Namespace: client.Namespace,
						BackendUrl: strings.Join([]string{HTTPS +
							client.Host, strings.ToLower(API),
							API_VERSION, WEB, client.Namespace, packageName,
							actionName + "." + utils.HTTP_FILE_EXTENSION},
							PATH_SEPARATOR),
						BackendMethod: gatewayMethodResponse.Method,
						Auth:          client.AuthToken,
					}

					requestApiDoc := whisk.Api{
						GatewayBasePath: gatewayBasePath,
						PathParameters:  pathParameters,
						GatewayRelPath:  gatewayRelPath,
						GatewayMethod:   strings.ToUpper(gatewayMethodResponse.Method),
						Namespace:       client.Namespace,
						ApiName:         apiName,
						Id:              strings.Join([]string{API, client.Namespace, gatewayRelPath}, ":"),
						Action:          &apiDocAction,
					}

					request := whisk.ApiCreateRequest{
						ApiDoc: &requestApiDoc,
					}

					// add a newly created ApiCreateRequest object to a list of requests
					requests = append(requests, &request)

					// Create an instance of ApiCreateRequestOptions
					options := whisk.ApiCreateRequestOptions{
						ResponseType: gatewayMethodResponse.Response,
					}
					apiPath := request.ApiDoc.ApiName + " " + request.ApiDoc.GatewayBasePath +
						request.ApiDoc.GatewayRelPath + " " + request.ApiDoc.GatewayMethod
					requestOptions[apiPath] = &options
				}
			}
		}
	}
	return requests, requestOptions, nil
}

func (dm *YAMLParser) getGatewayMethods() []string {
	methods := []string{}
	for k := range whisk.ApiVerbs {
		methods = append(methods, k)
	}
	return methods
}

func doesPathParamExist(params []string, param string) bool {
	for _, e := range params {
		if e == param {
			return true
		}
	}
	return false
}

func getPathParameterNames(path string) []string {
	var pathParameters []string
	pathElements := strings.Split(path, PATH_SEPARATOR)
	for _, e := range pathElements {
		paramName := getParamName(e)
		if len(paramName) > 0 {
			if !doesPathParamExist(pathParameters, paramName) {
				pathParameters = append(pathParameters, paramName)
			}
		}
	}
	return pathParameters
}

func generatePathParameters(relativePath string) []whisk.ApiParameter {
	pathParams := []whisk.ApiParameter{}

	pathParamNames := getPathParameterNames(relativePath)
	for _, paramName := range pathParamNames {
		param := whisk.ApiParameter{Name: paramName, In: "path", Required: true, Type: "string",
			Description: wski18n.T("Default description for '{{.name}}'", map[string]interface{}{"name": paramName})}
		pathParams = append(pathParams, param)
	}

	return pathParams
}

func isParam(param string) bool {
	if strings.HasPrefix(param, PARAM_OPENING_BRACKET) &&
		strings.HasSuffix(param, PARAM_CLOSING_BRACKET) {
		return true
	}
	return false
}

func getParamName(param string) string {
	paramName := ""
	if isParam(param) {
		paramName = param[1 : len(param)-1]
	}
	return paramName
}

func isGatewayBasePathValid(basePath string) bool {
	// return false if base path is empty string
	if len(basePath) == 0 {
		return false
	}
	// drop preceding "/" if exists
	if strings.HasPrefix(basePath, PATH_SEPARATOR) {
		basePath = basePath[1:]
	}
	// slice base path into substrings seperated by "/"
	// if there are more than one substrings, basePath has path parameters
	// basePath will have path parameters if substrings count is more than 1
	basePathElements := strings.Split(basePath, PATH_SEPARATOR)
	if len(basePathElements) > 1 {
		return false
	}
	return true
}
