/*
 * 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 (
	"strings"

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

var clientConfig *whisk.Config

type ManifestReader struct {
	serviceDeployer *ServiceDeployer
	IsUndeploy      bool
}

func NewManifestReader(serviceDeployer *ServiceDeployer) *ManifestReader {
	var dep ManifestReader
	dep.serviceDeployer = serviceDeployer

	return &dep
}

func (deployer *ManifestReader) ParseManifest() (*parsers.YAML, *parsers.YAMLParser, error) {
	dep := deployer.serviceDeployer
	manifestParser := parsers.NewYAMLParser()
	manifest, err := manifestParser.ParseManifest(dep.ManifestPath)

	if err != nil {
		return manifest, manifestParser, err
	}
	return manifest, manifestParser, nil
}

func (reader *ManifestReader) InitPackages(manifestParser *parsers.YAMLParser, manifest *parsers.YAML, managedAnnotations whisk.KeyValue) error {
	packages, inputs, err := manifestParser.ComposeAllPackages(reader.serviceDeployer.ProjectInputs, manifest, reader.serviceDeployer.ManifestPath, managedAnnotations)
	if err != nil {
		return err
	}
	reader.SetPackages(packages, inputs)
	return nil
}

// Wrapper parser to handle yaml dir
func (reader *ManifestReader) HandleYaml(manifestParser *parsers.YAMLParser, manifest *parsers.YAML, managedAnnotations whisk.KeyValue) error {

	var err error
	var manifestName = manifest.Filepath

	// pull the package inputs out of Deployment.Packages
	// so that they can be sent to all OW entities while they are being parsed and constructed
	// the main reason for sending Package inputs (normalized) to parser is
	// manifest file can have $TRIGGER_NAME as a trigger name, $RULE_NAME as a rule name, etc
	// which are being read by the parser and the way it works is, these variables are
	// treated as environment variables and tried to interpolate them but when these
	// variables are not defined in env., they are returned as an empty string and we
	// loose the env. variable name(TRIGGER_NAME), so before we loose that label,
	// we need to substitute it with its corresponding value from the inputs section
	inputs := make(map[string]parsers.PackageInputs, 0)
	for _, pkg := range reader.serviceDeployer.Deployment.Packages {
		inputs[pkg.Package.Name] = pkg.Inputs
	}

	deps, err := manifestParser.ComposeDependenciesFromAllPackages(manifest, reader.serviceDeployer.ProjectPath, reader.serviceDeployer.ManifestPath, managedAnnotations, inputs)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	actions, err := manifestParser.ComposeActionsFromAllPackages(manifest, reader.serviceDeployer.ManifestPath, managedAnnotations, inputs)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	sequences, err := manifestParser.ComposeSequencesFromAllPackages(reader.serviceDeployer.ClientConfig.Namespace, manifest, reader.serviceDeployer.ManifestPath, managedAnnotations, inputs)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	triggers, err := manifestParser.ComposeTriggersFromAllPackages(manifest, reader.serviceDeployer.ManifestPath, managedAnnotations, inputs)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	rules, err := manifestParser.ComposeRulesFromAllPackages(manifest, managedAnnotations, inputs)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	apis, responses, err := manifestParser.ComposeApiRecordsFromAllPackages(reader.serviceDeployer.ClientConfig, manifest, actions, sequences)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	api, response, err := manifestParser.ComposeApiRecordsFromSwagger(reader.serviceDeployer.ClientConfig, manifest)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	err = reader.SetDependencies(deps)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	err = reader.SetActions(actions)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	err = reader.SetSequences(sequences)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	err = reader.SetTriggers(triggers)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	err = reader.SetRules(rules)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	err = reader.SetApis(apis, responses)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	err = reader.SetSwaggerApi(api, response)
	if err != nil {
		return wskderrors.NewYAMLFileFormatError(manifestName, err)
	}

	return nil
}

func (reader *ManifestReader) SetPackages(packages map[string]*whisk.Package, inputs map[string]parsers.PackageInputs) error {

	dep := reader.serviceDeployer
	dep.mt.Lock()
	defer dep.mt.Unlock()

	for _, pkg := range packages {
		newPack := NewDeploymentPackage()
		newPack.Package = pkg
		newPack.Inputs = inputs[pkg.Name]
		dep.Deployment.Packages[pkg.Name] = newPack
	}
	return nil
}

func (reader *ManifestReader) SetDependencies(deps map[string]dependencies.DependencyRecord) error {

	dep := reader.serviceDeployer
	dep.mt.Lock()
	defer dep.mt.Unlock()

	for name, dependency := range deps {
		// name is <packagename>:<dependencylabel>
		depName := strings.Split(name, ":")[1]
		if len(depName) == 0 {
			return nil
		}
		if !dependency.IsBinding && !reader.IsUndeploy {
			if _, exists := dep.DependencyMaster[depName]; exists {
				if !dependencies.CompareDependencyRecords(dep.DependencyMaster[depName], dependency) {
					location := strings.Join([]string{dep.DependencyMaster[depName].Location, dependency.Location}, ",")
					errmsg := wski18n.T(wski18n.ID_ERR_DEPENDENCIES_WITH_SAME_LABEL_X_dependency_X_location_X,
						map[string]interface{}{wski18n.KEY_DEPENDENCY: depName,
							wski18n.KEY_LOCATION: location})
					return wskderrors.NewYAMLParserErr(dep.ManifestPath, errmsg)
				}
			}
			gitReader := dependencies.NewGitReader(depName, dependency)
			err := gitReader.CloneDependency()
			if err != nil {
				return err
			}
		}
		// store in two places (one local to package to preserve relationship, one in master record to check for conflics
		dep.Deployment.Packages[dependency.Packagename].Dependencies[depName] = dependency
		dep.DependencyMaster[depName] = dependency
	}

	return nil
}

func (reader *ManifestReader) SetActions(actions []utils.ActionRecord) error {
	dep := reader.serviceDeployer
	dep.mt.Lock()
	defer dep.mt.Unlock()

	for _, manifestAction := range actions {
		err := reader.checkAction(manifestAction)
		if err != nil {
			return err
		}
		dep.Deployment.Packages[manifestAction.Packagename].Actions[manifestAction.Action.Name] = manifestAction
	}
	return nil
}

func (reader *ManifestReader) SetSequences(sequences []utils.ActionRecord) error {
	dep := reader.serviceDeployer
	dep.mt.Lock()
	defer dep.mt.Unlock()

	for _, sequence := range sequences {
		// If the sequence name matches with any of the actions defined, return error
		if _, exists := dep.Deployment.Packages[sequence.Packagename].Actions[sequence.Action.Name]; exists {
			err := wski18n.T(wski18n.ID_ERR_SEQUENCE_HAVING_SAME_NAME_AS_ACTION_X_action_X,
				map[string]interface{}{wski18n.KEY_SEQUENCE: sequence.Action.Name})
			return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
		}
		err := reader.checkAction(sequence)
		if err != nil {
			return err
		}
		dep.Deployment.Packages[sequence.Packagename].Sequences[sequence.Action.Name] = sequence
	}

	return nil
}

func (reader *ManifestReader) SetTriggers(triggers []*whisk.Trigger) error {

	dep := reader.serviceDeployer

	dep.mt.Lock()
	defer dep.mt.Unlock()

	for _, trigger := range triggers {
		if _, exists := dep.Deployment.Triggers[trigger.Name]; exists {
			var feed string
			var existingFeed string
			for _, a := range dep.Deployment.Triggers[trigger.Name].Annotations {
				if a.Key == parsers.YAML_KEY_FEED {
					existingFeed = a.Value.(string)
				}
			}
			for _, a := range trigger.Annotations {
				if a.Key == parsers.YAML_KEY_FEED {
					feed = a.Value.(string)
				}
			}
			if feed != existingFeed {
				feed = fmt.Sprintf("%q", feed)
				existingFeed = fmt.Sprintf("%q", existingFeed)
				err := wski18n.T(wski18n.ID_ERR_CONFLICTING_TRIGGERS_ACROSS_PACKAGES_X_trigger_X_feed_X,
					map[string]interface{}{wski18n.KEY_TRIGGER: trigger.Name,
						wski18n.KEY_TRIGGER_FEED: strings.Join([]string{feed, existingFeed}, ", ")})
				return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
			}
		}
		dep.Deployment.Triggers[trigger.Name] = trigger
	}
	return nil
}

func (reader *ManifestReader) SetRules(rules []*whisk.Rule) error {
	dep := reader.serviceDeployer

	dep.mt.Lock()
	defer dep.mt.Unlock()

	for _, rule := range rules {
		if _, exists := dep.Deployment.Rules[rule.Name]; exists {
			action := rule.Action.(string)
			existingAction := dep.Deployment.Rules[rule.Name].Action.(string)
			trigger := rule.Trigger.(string)
			existingTrigger := dep.Deployment.Rules[rule.Name].Trigger.(string)
			if action != existingAction || trigger != existingTrigger {
				action = fmt.Sprintf("%q", action)
				existingAction = fmt.Sprintf("%q", existingAction)
				trigger = fmt.Sprintf("%q", trigger)
				existingTrigger = fmt.Sprintf("%q", existingTrigger)
				err := wski18n.T(wski18n.ID_ERR_CONFLICTING_RULES_ACROSS_PACKAGES_X_rule_X_action_X_trigger_X,
					map[string]interface{}{wski18n.KEY_RULE: rule.Name,
						wski18n.KEY_TRIGGER: strings.Join([]string{trigger, existingTrigger}, ", "),
						wski18n.KEY_ACTION:  strings.Join([]string{action, existingAction}, ", ")})
				return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
			}
		}
		dep.Deployment.Rules[rule.Name] = rule
	}
	return nil
}

func (reader *ManifestReader) SetApis(ar []*whisk.ApiCreateRequest, responses map[string]*whisk.ApiCreateRequestOptions) error {
	dep := reader.serviceDeployer

	dep.mt.Lock()
	defer dep.mt.Unlock()

	for _, api := range ar {
		apiPath := api.ApiDoc.ApiName + " " + api.ApiDoc.GatewayBasePath +
			api.ApiDoc.GatewayRelPath + " " + api.ApiDoc.GatewayMethod
		dep.Deployment.Apis[apiPath] = api
	}
	for apiPath, response := range responses {
		dep.Deployment.ApiOptions[apiPath] = response
	}

	return nil
}

func (reader *ManifestReader) SetSwaggerApi(api *whisk.ApiCreateRequest, response *whisk.ApiCreateRequestOptions) error {
	dep := reader.serviceDeployer

	dep.mt.Lock()
	defer dep.mt.Unlock()
	dep.Deployment.SwaggerApi = api
	dep.Deployment.SwaggerApiOptions = response
	return nil
}

// Check action record before deploying it
// action record is created by reading and composing action elements from manifest file
// Action.kind is mandatory which is set to
// (1) action runtime for an action and (2) set to "sequence" for a sequence
// Also, action executable code should be specified for any action
func (reader *ManifestReader) checkAction(action utils.ActionRecord) error {
	if action.Action.Exec.Kind == "" {
		err := wski18n.T(wski18n.ID_ERR_ACTION_WITHOUT_KIND_X_action_X,
			map[string]interface{}{wski18n.KEY_ACTION: action.Action.Name})
		return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
	}

	if action.Action.Exec.Code != nil {
		code := *action.Action.Exec.Code
		if code == "" && action.Action.Exec.Kind != parsers.YAML_KEY_SEQUENCE {
			err := wski18n.T(wski18n.ID_ERR_ACTION_WITHOUT_SOURCE_X_action_X,
				map[string]interface{}{wski18n.KEY_ACTION: action.Action.Name})
			return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
		}
	}

	return nil
}
