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

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, err := manifestParser.ComposeAllPackages(manifest, reader.serviceDeployer.ManifestPath, managedAnnotations)
	if err != nil {
		return err
	}
	reader.SetPackages(packages)

	return nil
}

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

	var err error
	var manifestName = manifest.Filepath

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

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

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

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

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

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

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

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

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

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

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

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

	return nil
}

func (reader *ManifestReader) SetDependencies(deps map[string]utils.DependencyRecord) error {
	for name, dep := range deps {
		n := strings.Split(name, ":")
		depName := n[1]
		if depName == "" {
			return nil
		}
		if !dep.IsBinding && !reader.IsUndeploy {
			if _, exists := reader.serviceDeployer.DependencyMaster[depName]; !exists {
				// dependency
				gitReader := utils.NewGitReader(depName, dep)
				err := gitReader.CloneDependency()
				if err != nil {
					return wskderrors.NewYAMLFileFormatError(depName, err)
				}
			} else {
				// TODO: we should do a check to make sure this dependency is compatible with an already installed one.
				// If not, we should throw dependency mismatch error.
			}
		}

		// store in two places (one local to package to preserve relationship, one in master record to check for conflics
		reader.serviceDeployer.Deployment.Packages[dep.Packagename].Dependencies[depName] = dep
		reader.serviceDeployer.DependencyMaster[depName] = dep

	}

	return nil
}

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

	dep := reader.serviceDeployer

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

	for _, pkg := range packages {
		_, exist := dep.Deployment.Packages[pkg.Name]
		if exist {
			// TODO(): i18n of error message (or create a new named error)
			// TODO(): Is there a better way to handle an existing dependency of same name?
			err := errors.New("Package [" + pkg.Name + "] exists already.")
			return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
		}
		newPack := NewDeploymentPackage()
		newPack.Package = pkg
		dep.Deployment.Packages[pkg.Name] = newPack
	}
	return nil
}

func (reader *ManifestReader) SetActions(actions []utils.ActionRecord) error {

	dep := reader.serviceDeployer

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

	for _, manifestAction := range actions {
		existAction, exists := reader.serviceDeployer.Deployment.Packages[manifestAction.Packagename].Actions[manifestAction.Action.Name]

		if exists == true {
			if existAction.Filepath == manifestAction.Filepath || manifestAction.Filepath == "" {
				// we're adding a filesystem detected action so just updated code and filepath if needed
				if manifestAction.Action.Exec.Kind != "" {
					existAction.Action.Exec.Kind = manifestAction.Action.Exec.Kind
				}

				if manifestAction.Action.Exec.Code != nil {
					code := *manifestAction.Action.Exec.Code
					if code != "" {
						existAction.Action.Exec.Code = manifestAction.Action.Exec.Code
					}
				}

				existAction.Action.Annotations = manifestAction.Action.Annotations
				existAction.Action.Limits = manifestAction.Action.Limits
				existAction.Action.Parameters = manifestAction.Action.Parameters
				existAction.Action.Version = manifestAction.Action.Version

				if manifestAction.Filepath != "" {
					existAction.Filepath = manifestAction.Filepath
				}

				err := reader.checkAction(existAction)
				if err != nil {
					return wskderrors.NewFileReadError(manifestAction.Filepath, err)
				}

			} else {
				// Action exists, but references two different sources
				// TODO(): i18n of error message (or create a new named error)
				err := errors.New("Conflict detected for action named [" +
					existAction.Action.Name + "].\nFound two locations for source file: [" +
					existAction.Filepath + "] and [" + manifestAction.Filepath + "]")
				return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
			}
		} else {
			// not a new action so update the action in the package
			err := reader.checkAction(manifestAction)
			if err != nil {
				return wskderrors.NewFileReadError(manifestAction.Filepath, err)
			}
			reader.serviceDeployer.Deployment.Packages[manifestAction.Packagename].Actions[manifestAction.Action.Name] = manifestAction
		}
	}

	return nil
}

// TODO create named errors
// 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 == "" {
		// TODO(): i18n of error message (or create a new named error)
		err := errors.New("Action [" + action.Action.Name + "] has no kind set.")
		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 {
			// TODO(): i18n of error message (or create a new named error)
			err := errors.New("Action [" + action.Action.Name + "] has no source code.")
			return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
		}
	}

	return nil
}

func (reader *ManifestReader) SetSequences(actions []utils.ActionRecord) error {
	dep := reader.serviceDeployer

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

	for _, seqAction := range actions {
		// check if the sequence action is exist in actions
		// If the sequence action exists in actions, return error
		_, exists := reader.serviceDeployer.Deployment.Packages[seqAction.Packagename].Actions[seqAction.Action.Name]
		if exists == true {
			// TODO(798): i18n of error message (or create a new named error)
			err := errors.New("Sequence action's name [" +
				seqAction.Action.Name + "] is already used by an action.")
			return wskderrors.NewYAMLParserErr(reader.serviceDeployer.ManifestPath, err)
		}
		existAction, exists := reader.serviceDeployer.Deployment.Packages[seqAction.Packagename].Sequences[seqAction.Action.Name]

		if exists == true {
			existAction.Action.Annotations = seqAction.Action.Annotations
			existAction.Action.Exec.Kind = "sequence"
			existAction.Action.Exec.Components = seqAction.Action.Exec.Components
			existAction.Action.Publish = seqAction.Action.Publish
			existAction.Action.Namespace = seqAction.Action.Namespace
			existAction.Action.Limits = seqAction.Action.Limits
			existAction.Action.Parameters = seqAction.Action.Parameters
			existAction.Action.Version = seqAction.Action.Version
		} else {
			// not a new action so update the action in the package
			err := reader.checkAction(seqAction)
			if err != nil {
				// TODO() Need a better error type here
				return wskderrors.NewFileReadError(seqAction.Filepath, err)
			}
			reader.serviceDeployer.Deployment.Packages[seqAction.Packagename].Sequences[seqAction.Action.Name] = seqAction
		}
	}

	return nil

}

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

	dep := reader.serviceDeployer

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

	for _, trigger := range triggers {
		existTrigger, exist := dep.Deployment.Triggers[trigger.Name]
		if exist {
			existTrigger.Name = trigger.Name
			existTrigger.ActivationId = trigger.ActivationId
			existTrigger.Namespace = trigger.Namespace
			existTrigger.Annotations = trigger.Annotations
			existTrigger.Version = trigger.Version
			existTrigger.Parameters = trigger.Parameters
			existTrigger.Publish = trigger.Publish
		} else {
			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 {
		existRule, exist := dep.Deployment.Rules[rule.Name]
		if exist {
			existRule.Name = rule.Name
			existRule.Publish = rule.Publish
			existRule.Version = rule.Version
			existRule.Namespace = rule.Namespace
			existRule.Action = rule.Action
			existRule.Trigger = rule.Trigger
			existRule.Status = rule.Status
		} else {
			dep.Deployment.Rules[rule.Name] = rule
		}

	}
	return nil
}

func (reader *ManifestReader) SetApis(ar []*whisk.ApiCreateRequest) error {
	dep := reader.serviceDeployer

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

	for _, api := range ar {
		existApi, exist := dep.Deployment.Apis[api.ApiDoc.Action.Name]
		if exist {
			existApi.ApiDoc.ApiName = api.ApiDoc.ApiName
		} else {
			dep.Deployment.Apis[api.ApiDoc.Action.Name] = api
		}

	}
	return nil
}
