/*
 * 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 (
	"fmt"
	"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/wski18n"
	"github.com/fatih/color"
	"github.com/spf13/cobra"
	"path"
	"sync"
    "os"
	"github.com/apache/incubator-openwhisk-wskdeploy/wskprint"
)

var wskpropsPath string

var client *whisk.Client
var wg sync.WaitGroup

// reportCmd represents the report command
var reportCmd = &cobra.Command{
	Use:   "report",
	SuggestFor: []string {"list"},
	Short: "Returns summary of what's been deployed on OpenWhisk in specific namespace",
	Long: `Command helps user get an overall report about what's been deployed
on OpenWhisk with specific OpenWhisk namespace. By default it will read the wsk property file
located under current user home.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		if wskpropsPath != "" {
			config, _ := deployers.NewWhiskConfig(wskpropsPath, utils.Flags.DeploymentPath, utils.Flags.ManifestPath, false)
            client, _ := deployers.CreateNewClient(config)
            return printDeploymentInfo(client)
		} else {
            //default to ~/.wskprops
            userHome := utils.GetHomeDirectory()
            propPath := path.Join(userHome, ".wskprops")
            config, _ := deployers.NewWhiskConfig(propPath, utils.Flags.DeploymentPath, utils.Flags.ManifestPath, false)
            client, _ := deployers.CreateNewClient(config)
            return printDeploymentInfo(client)
        }
	},
}

func init() {
	RootCmd.AddCommand(reportCmd)
	reportCmd.Flags().StringVarP(&wskpropsPath, "wskproppath", "w", path.Join(os.Getenv("HOME"), ".wskprops"), "path to wsk property file, default is to ~/.wskprops")

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// reportCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// reportCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")

}

var boldString = color.New(color.Bold).SprintFunc()

func printDeploymentInfo(client *whisk.Client) error {
	//We currently list packages, actions, triggers, rules.
	wg.Add(4)

	// TODO() i18n
	wskprint.PrintlnOpenWhiskStatus("----==== OpenWhisk Deployment Status ====----")
	// we set the default package list options
	pkgoptions := &whisk.PackageListOptions{false, 0, 0, 0, false}
	packages, _, err := client.Packages.List(pkgoptions)
    if err != nil {
        return err
    }

	// list all packages under current namespace.
	go func() {
		defer wg.Done()
		printList(packages)
	}()

	// list all the actions under all the packages.
	go func() error {
		defer wg.Done()
		acnoptions := &whisk.ActionListOptions{0, 0, false}
		for _, pkg := range packages {
			actions, _, err := client.Actions.List(pkg.Name, acnoptions)
            if err != nil {
                return err
            }
			printActionList(actions)
		}
        return nil
	}()

	// list all the triggers under current namespace.
	go func() error {
		defer wg.Done()
		troptions := &whisk.TriggerListOptions{0, 0, false}
        _, _, err := client.Triggers.List(troptions)
        if err != nil {
            return err
        }
		//printTriggerList(triggers)
        return nil
	}()

	// list all the rules under current namespace.
	go func() error {
		defer wg.Done()
		roptions := &whisk.RuleListOptions{0, 0, false}
		rules, _, err := client.Rules.List(roptions)
        if err != nil {
            return err
        }
		printRuleList(rules)
        return nil
	}()

	wg.Wait()

	return nil
}

// From below the codes are from the whisk-client package.
// http://github.com/openwhisk/openwhisk.git
func printList(collection interface{}) {
	switch collection := collection.(type) {
	case []whisk.Action:
		printActionList(collection)
	//case []whisk.Trigger
	//	printTriggerList(collection)
	case []whisk.Package:
		printPackageList(collection)
	case []whisk.Rule:
		printRuleList(collection)
	case []whisk.Namespace:
		printNamespaceList(collection)
	case []whisk.Activation:
		printActivationList(collection)
	}
}

func printRuleList(rules []whisk.Rule) {
	fmt.Fprintf(color.Output, "%s\n", boldString("rules"))
	for _, rule := range rules {
		publishState := wski18n.T("private")
		if *rule.Publish {
			publishState = wski18n.T("shared")
		}
		fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", rule.Namespace, rule.Name), publishState)
	}
}

func printPackageList(packages []whisk.Package) {
	fmt.Fprintf(color.Output, "%s\n", boldString("packages"))
	for _, xPackage := range packages {
		publishState := wski18n.T("private")
		if *xPackage.Publish {
			publishState = wski18n.T("shared")
		}
		fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", xPackage.Namespace, xPackage.Name), publishState)
	}
}

func printActionList(actions []whisk.Action) {
	fmt.Fprintf(color.Output, "%s\n", boldString("actions"))
	for _, action := range actions {
		publishState := wski18n.T("private")
		if *action.Publish {
			publishState = wski18n.T("shared")
		}
		kind := getValueString(action.Annotations, "exec")
		fmt.Printf("%-70s %s %s\n", fmt.Sprintf("/%s/%s", action.Namespace, action.Name), publishState, kind)
	}
}

/*
func printTriggerList(triggers whisk.Trigger) {
	fmt.Fprintf(color.Output, "%s\n", boldString("triggers"))
	for _, trigger := range triggers {
		publishState := wski18n.T("private")
		if trigger.Publish {
			publishState = wski18n.T("shared")
		}
		fmt.Printf("%-70s %s\n", fmt.Sprintf("/%s/%s", trigger.Namespace, trigger.Name), publishState)
	}
}*/

func getValueString(keyValueArr whisk.KeyValueArr, key string) string {
	var value interface{}
	var res string

	value = getValue(keyValueArr, key)
	castedValue, canCast := value.(string)

	if canCast {
		res = castedValue
	}

	whisk.Debug(whisk.DbgInfo, "Got string value '%v' for key '%s'\n", res, key)

	return res
}

func getValue(keyValueArr whisk.KeyValueArr, key string) interface{} {
	var res interface{}

	for i := 0; i < len(keyValueArr); i++ {
		if keyValueArr[i].Key == key {
			res = keyValueArr[i].Value
			break
		}
	}

	whisk.Debug(whisk.DbgInfo, "Got value '%v' from '%v' for key '%s'\n", res, keyValueArr, key)

	return res
}

func printNamespaceList(namespaces []whisk.Namespace) {
	fmt.Fprintf(color.Output, "%s\n", boldString("namespaces"))
	for _, namespace := range namespaces {
		fmt.Printf("%s\n", namespace.Name)
	}
}

func printActivationList(activations []whisk.Activation) {
	fmt.Fprintf(color.Output, "%s\n", boldString("activations"))
	for _, activation := range activations {
		fmt.Printf("%s %20s\n", activation.ActivationID, activation.Name)
	}
}
