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

import (
	"os"
	"path"
	"path/filepath"
	"strings"

	"github.com/apache/incubator-openwhisk-client-go/whisk"
	"github.com/apache/incubator-openwhisk-wskdeploy/deployers"
	"github.com/apache/incubator-openwhisk-wskdeploy/utils"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskderrors"
	"github.com/apache/incubator-openwhisk-wskdeploy/wski18n"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
	"github.com/spf13/cobra"
)

var stderr = ""

// Whisk Deploy has root command: wskdeploy
// wskdeploy is being created using Cobra Library
var RootCmd = &cobra.Command{
	Use:           "wskdeploy",
	SilenceErrors: true,
	SilenceUsage:  true,
	Short:         wski18n.T(wski18n.ID_CMD_DESC_SHORT_ROOT),
	Long:          wski18n.T(wski18n.ID_CMD_DESC_LONG_ROOT),
	RunE:          RootCmdImp,
}

func RootCmdImp(cmd *cobra.Command, args []string) error {
	return Deploy()
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	var err error

	os.Args, utils.Flags.Param, err = parseArgsForParams(os.Args)
	if err != nil {
		wskprint.PrintOpenWhiskError(err.Error())
		os.Exit(-1)
	}

	if err = RootCmd.Execute(); err != nil {
		wskprint.PrintOpenWhiskFromError(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	// Defining Persistent Flags of Whisk Deploy Root command (wskdeploy)
	// Persistent flags are global in terms of its availability and acceptable
	// with any other Whisk Deploy command e.g. undeploy, export, etc.
	// TODO() Publish command, not completed
	// TODO() Report command, not completed
	// TODO() have a single function that conditionally (i.e., Trace=true) prints ALL Flags
	RootCmd.PersistentFlags().StringVar(&utils.Flags.CfgFile, FLAG_CONFIG, "", wski18n.T(wski18n.ID_CMD_FLAG_CONFIG))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.ProjectPath, FLAG_PROJECT, FLAG_PROJECT_SHORT, ".", wski18n.T(wski18n.ID_CMD_FLAG_PROJECT))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.ManifestPath, FLAG_MANIFEST, FLAG_MANIFEST_SHORT, "", wski18n.T(wski18n.ID_CMD_FLAG_MANIFEST))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.DeploymentPath, FLAG_DEPLOYMENT, FLAG_DEPLOYMENT_SHORT, "", wski18n.T(wski18n.ID_CMD_FLAG_DEPLOYMENT))
	RootCmd.PersistentFlags().BoolVarP(&utils.Flags.Strict, FLAG_STRICT, FLAG_STRICT_SHORT, false, wski18n.T(wski18n.ID_CMD_FLAG_STRICT))
	RootCmd.PersistentFlags().BoolVarP(&utils.Flags.Preview, FLAG_PREVIEW, "", false, wski18n.T(wski18n.ID_CMD_FLAG_PREVIEW))
	RootCmd.PersistentFlags().BoolVarP(&utils.Flags.Verbose, FLAG_VERBOSE, FLAG_VERBOSE_SHORT, false, wski18n.T(wski18n.ID_CMD_FLAG_VERBOSE))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.ApiHost, FLAG_API_HOST, "", "", wski18n.T(wski18n.ID_CMD_FLAG_API_HOST))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.Namespace, FLAG_NAMESPACE, FLAG_NAMESPACE_SHORT, "", wski18n.T(wski18n.ID_CMD_FLAG_NAMESPACE))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.Auth, FLAG_AUTH, FLAG_AUTH_SHORT, "", wski18n.T(wski18n.ID_CMD_FLAG_AUTH_KEY))
	RootCmd.PersistentFlags().StringVar(&utils.Flags.ApiVersion, FLAG_APIVERSION, "", wski18n.T(wski18n.ID_CMD_FLAG_API_VERSION))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.Key, FLAG_KEY, FLAG_KEY_SHORT, "", wski18n.T(wski18n.ID_CMD_FLAG_KEY_FILE))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.Cert, FLAG_CERT, FLAG_CERT_SHORT, "", wski18n.T(wski18n.ID_CMD_FLAG_CERT_FILE))
	RootCmd.PersistentFlags().BoolVarP(&utils.Flags.Managed, FLAG_MANAGED, "", false, wski18n.T(wski18n.ID_CMD_FLAG_MANAGED))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.ProjectName, FLAG_PROJECTNAME, "", "", wski18n.T(wski18n.ID_CMD_FLAG_PROJECTNAME))
	RootCmd.PersistentFlags().BoolVarP(&utils.Flags.Trace, FLAG_TRACE, FLAG_TRACE_SHORT, false, wski18n.T(wski18n.ID_CMD_FLAG_TRACE))
	RootCmd.PersistentFlags().StringSliceVarP(&utils.Flags.Param, FLAG_PARAM, "", []string{}, wski18n.T(wski18n.ID_CMD_FLAG_PARAM))
	RootCmd.PersistentFlags().StringVarP(&utils.Flags.ParamFile, FLAG_PARAMFILE, FLAG_PARAMFILE_SHORT, "", wski18n.T(wski18n.ID_CMD_FLAG_PARAM_FILE))
	RootCmd.PersistentFlags().MarkHidden(FLAG_TRACE)
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	userHome := utils.GetHomeDirectory()
	defaultPath := path.Join(userHome, whisk.DEFAULT_LOCAL_CONFIG)
	if utils.Flags.CfgFile != "" {

		// Read the file as a wskprops file, to check if it is valid.
		_, err := whisk.ReadProps(utils.Flags.CfgFile)
		if err != nil {
			utils.Flags.CfgFile = defaultPath
			warn := wski18n.T(wski18n.ID_WARN_CONFIG_INVALID_X_path_X,
				map[string]interface{}{
					wski18n.KEY_PATH: utils.Flags.CfgFile})
			wskprint.PrintOpenWhiskWarning(warn)
		}

	} else {
		utils.Flags.CfgFile = defaultPath
	}
}

// TODO() add Trace of runtimes found at apihost
func setSupportedRuntimes(apiHost string) {
	op, error := utils.ParseOpenWhisk(apiHost)
	if error == nil {
		utils.SupportedRunTimes = utils.ConvertToMap(op)
		utils.DefaultRunTimes = utils.DefaultRuntimes(op)
		utils.FileExtensionRuntimeKindMap = utils.FileExtensionRuntimes(op)
		utils.FileRuntimeExtensionsMap = utils.FileRuntimeExtensions(op)
	}
}

func displayCommandUsingFilenameMessage(command string, filetype string, path string) {
	msg := wski18n.T(wski18n.ID_MSG_COMMAND_USING_X_cmd_X_filetype_X_path_X,
		map[string]interface{}{
			wski18n.KEY_CMD:       command,
			wski18n.KEY_FILE_TYPE: filetype,
			wski18n.KEY_PATH:      path})
	wskprint.PrintlnOpenWhiskVerbose(utils.Flags.Verbose, msg)
}

func loadDefaultManifestFileFromProjectPath(command string, projectPath string) error {

	if _, err := os.Stat(path.Join(projectPath, utils.ManifestFileNameYaml)); err == nil {
		utils.Flags.ManifestPath = path.Join(projectPath, utils.ManifestFileNameYaml)
	} else if _, err := os.Stat(path.Join(projectPath, utils.ManifestFileNameYml)); err == nil {
		utils.Flags.ManifestPath = path.Join(projectPath, utils.ManifestFileNameYml)
	} else {
		stderr = wski18n.T(wski18n.ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X,
			map[string]interface{}{wski18n.KEY_PATH: projectPath})
		return wskderrors.NewErrorManifestFileNotFound(projectPath, stderr)
	}
	displayCommandUsingFilenameMessage(command, wski18n.MANIFEST_FILE, utils.Flags.ManifestPath)
	return nil
}

func loadDefaultDeploymentFileFromProjectPath(command string, projectPath string) error {

	if _, err := os.Stat(path.Join(projectPath, utils.DeploymentFileNameYaml)); err == nil {
		utils.Flags.DeploymentPath = path.Join(projectPath, utils.DeploymentFileNameYaml)
	} else if _, err := os.Stat(path.Join(projectPath, utils.DeploymentFileNameYml)); err == nil {
		utils.Flags.DeploymentPath = path.Join(projectPath, utils.DeploymentFileNameYml)
	}
	displayCommandUsingFilenameMessage(command, wski18n.DEPLOYMENT_FILE, utils.Flags.DeploymentPath)
	return nil
}

func Deploy() error {

	// Convey flags for verbose and trace to Go client
	whisk.SetVerbose(utils.Flags.Verbose)
	whisk.SetDebug(utils.Flags.Trace)

	project_Path := strings.TrimSpace(utils.Flags.ProjectPath)
	if len(project_Path) == 0 {
		project_Path = utils.DEFAULT_PROJECT_PATH
	}
	projectPath, _ := filepath.Abs(project_Path)

	// If manifest filename is not provided, attempt to load default manifests from project path
	// default manifests are manifest.yaml and manifest.yml
	// return failure if none of the default manifest files were found
	if utils.Flags.ManifestPath == "" {
		if err := loadDefaultManifestFileFromProjectPath(wski18n.CMD_DEPLOY, projectPath); err != nil {
			return err
		}
	}

	// If deployment filename is not provided, attempt to load default deployment files from project path
	// default deployments are deployment.yaml and deployment.yml
	// continue processing manifest file, even if none of the default
	// deployment files were found as deployment files are optional
	if utils.Flags.DeploymentPath == "" {
		if err := loadDefaultDeploymentFileFromProjectPath(wski18n.CMD_DEPLOY, projectPath); err != nil {
			return err
		}
	}

	if utils.MayExists(utils.Flags.ManifestPath) {

		// Create an instance of ServiceDeployer
		var deployer = deployers.NewServiceDeployer()
		// Set Project Path, Manifest Path, and Deployment Path of ServiceDeployer
		deployer.ProjectPath = projectPath
		deployer.ManifestPath = utils.Flags.ManifestPath
		deployer.DeploymentPath = utils.Flags.DeploymentPath
		deployer.Preview = utils.Flags.Preview
		deployer.Report = utils.Flags.Report

		// master record of any dependency that has been downloaded
		deployer.DependencyMaster = make(map[string]utils.DependencyRecord)

		// Read credentials from Configuration file, manifest file or deployment file
		clientConfig, error := deployers.NewWhiskConfig(
			utils.Flags.CfgFile,
			utils.Flags.DeploymentPath,
			utils.Flags.ManifestPath)
		if error != nil {
			return error
		}

		whiskClient, error := deployers.CreateNewClient(clientConfig)
		if error != nil {
			return error
		}

		deployer.Client = whiskClient
		deployer.ClientConfig = clientConfig

		// The auth, apihost and namespace have been chosen, so that we can check the supported runtimes here.
		setSupportedRuntimes(clientConfig.Host)

		// Construct Deployment Plan
		err := deployer.ConstructDeploymentPlan()
		if err != nil {
			return err
		}

		// Deploy all OW entities
		err = deployer.Deploy()
		if err != nil {
			return err
		} else {
			return nil
		}

	} else {
		errString := wski18n.T(wski18n.ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X,
			map[string]interface{}{wski18n.KEY_PATH: utils.Flags.ManifestPath})
		whisk.Debug(whisk.DbgError, errString)
		return wskderrors.NewErrorManifestFileNotFound(utils.Flags.ManifestPath, errString)
	}

}

func Undeploy() error {

	// Convey flags for verbose and trace to Go client
	whisk.SetVerbose(utils.Flags.Verbose)
	whisk.SetDebug(utils.Flags.Trace)

	if len(utils.Flags.ProjectName) != 0 {
		var deployer = deployers.NewServiceDeployer()
		deployer.Preview = utils.Flags.Preview

		clientConfig, error := deployers.NewWhiskConfig(utils.Flags.CfgFile, "", "")
		if error != nil {
			return error
		}

		whiskClient, error := deployers.CreateNewClient(clientConfig)
		if error != nil {
			return error
		}

		deployer.Client = whiskClient
		deployer.ClientConfig = clientConfig

		// The auth, apihost and namespace have been chosen, so that we can check the supported runtimes here.
		setSupportedRuntimes(clientConfig.Host)

		err := deployer.UnDeployProject()
		if err != nil {
			return err
		}

		return nil
	}

	project_Path := strings.TrimSpace(utils.Flags.ProjectPath)
	if len(project_Path) == 0 {
		project_Path = utils.DEFAULT_PROJECT_PATH
	}
	projectPath, _ := filepath.Abs(project_Path)

	// If manifest filename is not provided, attempt to load default manifests from project path
	if utils.Flags.ManifestPath == "" {
		if err := loadDefaultManifestFileFromProjectPath(wski18n.CMD_UNDEPLOY, projectPath); err != nil {
			return err
		}
	}

	if utils.Flags.DeploymentPath == "" {

		if err := loadDefaultDeploymentFileFromProjectPath(wski18n.CMD_UNDEPLOY, projectPath); err != nil {
			return err
		}
	}

	if utils.FileExists(utils.Flags.ManifestPath) {

		var deployer = deployers.NewServiceDeployer()
		deployer.ProjectPath = utils.Flags.ProjectPath
		deployer.ManifestPath = utils.Flags.ManifestPath
		deployer.DeploymentPath = utils.Flags.DeploymentPath
		deployer.Preview = utils.Flags.Preview

		clientConfig, error := deployers.NewWhiskConfig(utils.Flags.CfgFile, utils.Flags.DeploymentPath, utils.Flags.ManifestPath)
		if error != nil {
			return error
		}

		whiskClient, error := deployers.CreateNewClient(clientConfig)
		if error != nil {
			return error
		}

		deployer.Client = whiskClient
		deployer.ClientConfig = clientConfig

		// The auth, apihost and namespace have been chosen, so that we can check the supported runtimes here.
		setSupportedRuntimes(clientConfig.Host)

		verifiedPlan, err := deployer.ConstructUnDeploymentPlan()
		if err != nil {
			return err
		}

		err = deployer.UnDeploy(verifiedPlan)
		if err != nil {
			return err
		} else {
			return nil
		}
	} else {
		errString := wski18n.T(wski18n.ID_ERR_MANIFEST_FILE_NOT_FOUND_X_path_X,
			map[string]interface{}{wski18n.KEY_PATH: utils.Flags.ManifestPath})
		return wskderrors.NewErrorManifestFileNotFound(utils.Flags.ManifestPath, errString)
	}
}
