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

import (
	"net/http"
	"strings"

	"github.com/apache/openwhisk-client-go/whisk"
	"github.com/apache/openwhisk-wskdeploy/parsers"
	"github.com/apache/openwhisk-wskdeploy/utils"
	"github.com/apache/openwhisk-wskdeploy/wskderrors"
	"github.com/apache/openwhisk-wskdeploy/wskenv"
	"github.com/apache/openwhisk-wskdeploy/wski18n"
	"github.com/apache/openwhisk-wskdeploy/wskprint"
)

func (deployer *ServiceDeployer) UpdatePackageInputs() error {
	var paramsCLI interface{}
	var err error
	var inputsWithoutValue []string

	// check if any inputs/parameters are specified in CLI using --param or --param-file
	// store params in Key/value pairs
	if len(utils.Flags.Param) > 0 {
		paramsCLI, err = utils.GetJSONFromStrings(utils.Flags.Param, false)
		if err != nil {
			return err
		}
	}

	if paramsCLI != nil {
		// iterate over each package to update its set of inputs with CLI
		for _, pkg := range deployer.Deployment.Packages {
			// iterate over each input of type Parameter
			for name, param := range pkg.Inputs.Inputs {
				inputValue := param.Value
				// check if this particular input is specified on CLI
				if v, ok := paramsCLI.(map[string]interface{})[name]; ok {
					inputValue = wskenv.InterpolateStringWithEnvVar(v)
				}
				param.Value = inputValue
				pkg.Inputs.Inputs[name] = param
			}
		}
	}
	for _, pkg := range deployer.Deployment.Packages {
		keyValArr := make([]whisk.KeyValue, 0)
		if pkg.Inputs.Inputs != nil || len(pkg.Inputs.Inputs) != 0 {
			for k, v := range pkg.Inputs.Inputs {
				if v.Required {
					if parsers.IsTypeDefaultValue(v.Type, v.Value) {
						inputsWithoutValue = append(inputsWithoutValue, k)
					}
				}
				if _, ok := deployer.ProjectInputs[k]; !ok {
					keyVal := whisk.KeyValue{
						Key:   k,
						Value: v.Value,
					}
					keyValArr = append(keyValArr, keyVal)
				}
			}
		}
		pkg.Package.Parameters = keyValArr
	}

	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, ", ")})
		if utils.Flags.Report {
			wskprint.PrintOpenWhiskError(errMessage)
		} else {
			return wskderrors.NewYAMLFileFormatError(deployer.ManifestPath, errMessage)
		}
	}

	return nil
}

func (deployer *ServiceDeployer) UnDeployProjectAssets() error {

	// calculate all the project entities such as packages, actions, sequences,
	// triggers, and rules based on the project name in "whisk-managed" annotation
	deployer.SetProjectAssets(utils.Flags.ProjectName)
	// calculate all the dependencies based on the project name
	projectDeps, err := deployer.SetProjectDependencies(utils.Flags.ProjectName)
	if err != nil {
		return err
	}

	// show preview of which all OpenWhisk entities will be deployed
	if utils.Flags.Preview {
		deployer.printDeploymentAssets(deployer.Deployment)
		for _, deps := range projectDeps {
			deployer.printDeploymentAssets(deps)
		}
		return nil
	}

	// now, undeploy all those project dependencies if not used by
	// any other project or packages
	for _, deps := range projectDeps {
		if err := deployer.unDeployAssets(deps); err != nil {
			return err
		}
	}

	// undeploy all the project entities
	return deployer.unDeployAssets(deployer.Deployment)

	return nil
}

// based on the project name set in "whisk-managed" annotation
// calculate and determine list of packages, actions, sequences, rules and triggers
func (deployer *ServiceDeployer) SetProjectAssets(projectName string) error {

	if err := deployer.SetProjectPackages(projectName); err != nil {
		return err
	}

	if err := deployer.SetPackageActionsAndSequences(projectName); err != nil {
		return err
	}

	if err := deployer.SetProjectTriggers(projectName); err != nil {
		return err
	}

	if err := deployer.SetProjectRules(projectName); err != nil {
		return err
	}

	if err := deployer.SetProjectApis(projectName); err != nil {
		return err
	}

	return nil
}

// check if project name matches with the one in "whisk-managed" annotation
func (deployer *ServiceDeployer) isManagedEntity(a interface{}, projectName string) bool {
	if a != nil {
		ta := a.(map[string]interface{})
		if ta[utils.OW_PROJECT_NAME] == projectName {
			return true
		}
	}
	return false
}

// get an instance of *whisk.Package for the specified package name
func (deployer *ServiceDeployer) getPackage(packageName string) (*DeploymentPackage, error) {
	var err error
	var p *whisk.Package
	var response *http.Response
	err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
		p, response, err = deployer.Client.Packages.Get(packageName)
		return err
	})
	if err != nil {
		return nil, createWhiskClientError(err.(*whisk.WskError), response, parsers.YAML_KEY_PACKAGE, false)
	}
	newPack := NewDeploymentPackage()
	newPack.Package = p
	return newPack, nil

}

// capture all the packages with "whisk-managed" annotations and matching project name
func (deployer *ServiceDeployer) SetProjectPackages(projectName string) error {
	// retrieve a list of all the packages available under the namespace
	listOfPackages, _, err := deployer.Client.Packages.List(&whisk.PackageListOptions{})
	if err != nil {
		return nil
	}
	for _, pkg := range listOfPackages {
		if deployer.isManagedEntity(pkg.Annotations.GetValue(utils.MANAGED), projectName) {
			p, err := deployer.getPackage(pkg.Name)
			if err != nil {
				return err
			}
			deployer.Deployment.Packages[pkg.Name] = p
		}
	}

	return nil
}

// get a list of actions/sequences of a given package name
func (deployer *ServiceDeployer) getPackageActionsAndSequences(packageName string, projectName string) (map[string]utils.ActionRecord, map[string]utils.ActionRecord, error) {
	listOfActions := make(map[string]utils.ActionRecord, 0)
	listOfSequences := make(map[string]utils.ActionRecord, 0)

	actions, _, err := deployer.Client.Actions.List(packageName, &whisk.ActionListOptions{})
	if err != nil {
		return listOfActions, listOfSequences, err
	}
	for _, action := range actions {
		if deployer.isManagedEntity(action.Annotations.GetValue(utils.MANAGED), projectName) {
			var a *whisk.Action
			var response *http.Response
			err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
				a, response, err = deployer.Client.Actions.Get(packageName+parsers.PATH_SEPARATOR+action.Name, false)
				return err
			})
			if err != nil {
				return listOfActions, listOfSequences, createWhiskClientError(err.(*whisk.WskError), response, parsers.YAML_KEY_ACTION, false)
			}
			ar := utils.ActionRecord{Action: a, Packagename: packageName}
			if a.Exec.Kind == parsers.YAML_KEY_SEQUENCE {
				listOfSequences[action.Name] = ar
			} else {
				listOfActions[action.Name] = ar
			}
		}
	}
	return listOfActions, listOfSequences, err
}

// capture all the actions/sequences with "whisk-managed" annotations and matching project name
func (deployer *ServiceDeployer) SetPackageActionsAndSequences(projectName string) error {
	for _, pkg := range deployer.Deployment.Packages {
		a, s, err := deployer.getPackageActionsAndSequences(pkg.Package.Name, projectName)
		if err != nil {
			return err
		}
		deployer.Deployment.Packages[pkg.Package.Name].Actions = a
		deployer.Deployment.Packages[pkg.Package.Name].Sequences = s
	}
	return nil
}

// get a list of triggers from a given project name
func (deployer *ServiceDeployer) getProjectTriggers(projectName string) (map[string]*whisk.Trigger, error) {
	triggers := make(map[string]*whisk.Trigger, 0)
	listOfTriggers, _, err := deployer.Client.Triggers.List(&whisk.TriggerListOptions{})
	if err != nil {
		return triggers, nil
	}
	for _, trigger := range listOfTriggers {
		if deployer.isManagedEntity(trigger.Annotations.GetValue(utils.MANAGED), projectName) {
			var t *whisk.Trigger
			var response *http.Response
			err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
				t, response, err = deployer.Client.Triggers.Get(trigger.Name)
				return err
			})
			if err != nil {
				return triggers, createWhiskClientError(err.(*whisk.WskError), response, parsers.YAML_KEY_TRIGGER, false)
			}
			triggers[trigger.Name] = t
		}
	}
	return triggers, nil
}

// capture all the triggers with "whisk-managed" annotations and matching project name
func (deployer *ServiceDeployer) SetProjectTriggers(projectName string) error {
	t, err := deployer.getProjectTriggers(projectName)
	if err != nil {
		return err
	}
	deployer.Deployment.Triggers = t
	return nil
}

// get a list of rules from a given project name
func (deployer *ServiceDeployer) getProjectRules(projectName string) (map[string]*whisk.Rule, error) {
	rules := make(map[string]*whisk.Rule, 0)
	listOfRules, _, err := deployer.Client.Rules.List(&whisk.RuleListOptions{})
	if err != nil {
		return rules, nil
	}
	for _, rule := range listOfRules {
		if deployer.isManagedEntity(rule.Annotations.GetValue(utils.MANAGED), projectName) {
			var r *whisk.Rule
			var response *http.Response
			err = retry(DEFAULT_ATTEMPTS, DEFAULT_INTERVAL, func() error {
				r, response, err = deployer.Client.Rules.Get(rule.Name)
				return err
			})
			if err != nil {
				return rules, createWhiskClientError(err.(*whisk.WskError), response, parsers.YAML_KEY_RULE, false)
			}
			rules[rule.Name] = r
		}
	}
	return rules, nil
}

// capture all the rules with "whisk-managed" annotations and matching project name
func (deployer *ServiceDeployer) SetProjectRules(projectName string) error {
	r, err := deployer.getProjectRules(projectName)
	if err != nil {
		return err
	}
	deployer.Deployment.Rules = r
	return nil
}

// "whisk-manged" annotation stores package name with namespace such as
// /<namespace>/<package name>
// parse this kind of structure to determine package name
func (deployer *ServiceDeployer) filterPackageName(name string) string {
	s := strings.SplitAfterN(name, "/", 3)
	if len(s) == 3 && len(s[2]) != 0 {
		return s[2]
	}
	return ""
}

// determine if any other package on the server is using the dependent package
func (deployer *ServiceDeployer) isPackageUsedByOtherPackages(projectName string, depPackageName string) bool {
	// retrieve a list of packages on the server
	listOfPackages, _, err := deployer.Client.Packages.List(&whisk.PackageListOptions{})
	if err != nil {
		return false
	}
	for _, pkg := range listOfPackages {
		if a := pkg.Annotations.GetValue(utils.MANAGED); a != nil {
			ta := a.(map[string]interface{})
			// compare project names of the given package and other packages from server
			// we want to skip comparing packages from the same project
			if ta[utils.OW_PROJECT_NAME] != projectName {
				d := a.(map[string]interface{})[utils.OW_PROJECT_DEPS]
				listOfDeps := d.([]interface{})
				// iterate over a list of dependencies of a package
				// to determine whether it has listed the dependent package as its dependency as well
				// in such case, we dont want to undeploy dependent package if its used by any other package
				for _, dep := range listOfDeps {
					name := deployer.filterPackageName(dep.(map[string]interface{})[wski18n.KEY_KEY].(string))
					if name == depPackageName {
						return true
					}

				}

			}

		}
	}
	return false
}

// derive a map of dependent packages using "whisk-managed" annotation
// "whisk-managed" annotation has a list of dependent packages in "projectDeps"
// projectDeps is a list of key value pairs with its own "whisk-managed" annotation
// for a given package, get the list of dependent packages
// for each dependent package, determine whether any other package is using it or not
// if not, collect a list of actions, sequences, triggers, and rules of the dependent package
// and delete them in order following by deleting the package itself
func (deployer *ServiceDeployer) SetProjectDependencies(projectName string) ([]*DeploymentProject, error) {
	projectDependencies := make([]*DeploymentProject, 0)
	// iterate over each package in a given project
	for _, pkg := range deployer.Deployment.Packages {
		// get the "whisk-managed" annotation
		if a := pkg.Package.Annotations.GetValue(utils.MANAGED); a != nil {
			// read the list of dependencies from "projectDeps"
			d := a.(map[string]interface{})[utils.OW_PROJECT_DEPS]
			listOfDeps := d.([]interface{})
			// iterate over a list of dependencies
			for _, dep := range listOfDeps {
				// dependent package name is in form of "/<namespace>/<package-name>
				// filter it to derive the package name
				name := deployer.filterPackageName(dep.(map[string]interface{})[wski18n.KEY_KEY].(string))
				// undeploy dependent package if its not used by any other package
				if !deployer.isPackageUsedByOtherPackages(projectName, name) {
					// get the *whisk.Package object for the given dependent package
					p, err := deployer.getPackage(name)
					if err != nil {
						return projectDependencies, err
					}
					// construct a new DeploymentProject for each dependency
					depProject := NewDeploymentProject()
					depProject.Packages[p.Package.Name] = p
					// Now, get the project name of dependent package so that
					// we can get other entities from that project
					pa := p.Package.Annotations.GetValue(utils.MANAGED)
					depProjectName := (pa.(map[string]interface{})[utils.OW_PROJECT_NAME]).(string)
					// get a list of actions and sequences of a dependent package
					actions, sequences, err := deployer.getPackageActionsAndSequences(p.Package.Name, depProjectName)
					if err != nil {
						return projectDependencies, err
					}
					depProject.Packages[p.Package.Name].Actions = actions
					depProject.Packages[p.Package.Name].Sequences = sequences
					// get a list of triggers of a dependent project
					t, err := deployer.getProjectTriggers(depProjectName)
					if err != nil {
						return projectDependencies, err
					}
					depProject.Triggers = t
					// get a list of rules of a dependent project
					r, err := deployer.getProjectRules(depProjectName)
					if err != nil {
						return projectDependencies, err
					}
					depProject.Rules = r
					projectDependencies = append(projectDependencies, depProject)
				}
			}
		}
	}
	return projectDependencies, nil
}

func (deployer *ServiceDeployer) SetProjectApis(projectName string) error {
	return nil
}
