/*
 * 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/incubator-openwhisk-client-go/whisk"
	"github.com/apache/incubator-openwhisk-wskdeploy/parsers"
	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
	"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"
)

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
}
