/*
 * Copyright 2019-present Ciena Corporation
 *
 * Licensed 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 commands

import (
	"context"
	"fmt"
	"github.com/fullstorydev/grpcurl"
	flags "github.com/jessevdk/go-flags"
	"github.com/jhump/protoreflect/dynamic"
	"github.com/opencord/voltctl/pkg/format"
	"github.com/opencord/voltctl/pkg/model"
	"google.golang.org/grpc"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	"log"
	"strings"
)

type SetLogLevelOutput struct {
	ComponentName string
	Status        string
	Error         string
}

type SetLogLevelOpts struct {
	OutputOptions
	Package string `short:"p" long:"package" description:"Package name to set filter level"`
	Args    struct {
		Level     string
		Component []string
	} `positional-args:"yes" required:"yes"`
}

type GetLogLevelsOpts struct {
	ListOutputOptions
	Args struct {
		Component []string
	} `positional-args:"yes" required:"yes"`
}

type ListLogLevelsOpts struct {
	ListOutputOptions
}

type LogLevelOpts struct {
	SetLogLevel   SetLogLevelOpts   `command:"set"`
	GetLogLevels  GetLogLevelsOpts  `command:"get"`
	ListLogLevels ListLogLevelsOpts `command:"list"`
}

var logLevelOpts = LogLevelOpts{}

const (
	DEFAULT_LOGLEVELS_FORMAT   = "table{{ .ComponentName }}\t{{.PackageName}}\t{{.Level}}"
	DEFAULT_SETLOGLEVEL_FORMAT = "table{{ .ComponentName }}\t{{.Status}}\t{{.Error}}"
)

func RegisterLogLevelCommands(parent *flags.Parser) {
	_, err := parent.AddCommand("loglevel", "loglevel commands", "Get and set log levels", &logLevelOpts)
	if err != nil {
		panic(err)
	}
}

func MapListAppend(m map[string][]string, name string, item string) {
	list, okay := m[name]
	if okay {
		m[name] = append(list, item)
	} else {
		m[name] = []string{item}
	}
}

/*
 * A roundabout way of going of using the LogLevel enum to map from
 * a string to an integer that we can pass into the dynamic
 * proto.
 *
 * TODO: There's probably an easier way.
 */
func LogLevelStringToInt(logLevelString string) (int32, error) {
	ProcessGlobalOptions() // required for GetMethod()

	/*
	 * Use GetMethod() to get us a descriptor on the proto file we're
	 * interested in.
	 */

	descriptor, _, err := GetMethod("update-log-level")
	if err != nil {
		return 0, err
	}

	/*
	 * Map string LogLevel to enumerated type LogLevel
	 * We have descriptor from above, which is a DescriptorSource
	 * We can use FindSymbol to get at the message
	 */

	loggingSymbol, err := descriptor.FindSymbol("common.LogLevel")
	if err != nil {
		return 0, err
	}

	/*
	 * LoggingSymbol is a Descriptor, but not a MessageDescrptior,
	 * so we can't look at it's fields yet. Go back to the file,
	 * call FindMessage to get the Message, then we can get the
	 * embedded enum.
	 */

	loggingFile := loggingSymbol.GetFile()
	logLevelMessage := loggingFile.FindMessage("common.LogLevel")
	logLevelEnumType := logLevelMessage.GetNestedEnumTypes()[0]
	enumLogLevel := logLevelEnumType.FindValueByName(logLevelString)

	if enumLogLevel == nil {
		return 0, fmt.Errorf("Unknown log level %s", logLevelString)
	}

	return enumLogLevel.GetNumber(), nil
}

// Validate a list of component names and throw an error if any one of them is bad.
func ValidateComponentNames(kube_to_arouter map[string][]string, names []string) error {
	var badNames []string
	for _, name := range names {
		_, ok := kube_to_arouter[name]
		if !ok {
			badNames = append(badNames, name)
		}
	}

	if len(badNames) > 0 {
		return fmt.Errorf("Unknown components: %s", strings.Join(badNames, ","))
	} else {
		return nil
	}
}

func BuildKubernetesNameMap() (map[string][]string, map[string]string, error) {
	kube_to_arouter := make(map[string][]string)
	arouter_to_kube := make(map[string]string)

	// use the current context in kubeconfig
	config, err := clientcmd.BuildConfigFromFlags("", GlobalOptions.K8sConfig)
	if err != nil {
		return nil, nil, err
	}

	// create the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, nil, err
	}

	pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{
		LabelSelector: "app.kubernetes.io/part-of=voltha",
	})
	if err != nil {
		return nil, nil, err
	}

	if len(pods.Items) == 0 {
		return nil, nil, fmt.Errorf("No Voltha pods found in Kubernetes -- verify pod is setup")
	}

	for _, pod := range pods.Items {
		app, ok := pod.Labels["app"]
		if !ok {
			continue
		}

		var arouter_name string

		switch app {
		case "voltha-api-server":
			/*
			 * Assumes a single api_server for now.
			 * TODO: Make labeling changes in charts to be able to derive name from labels
			 */
			arouter_name = "api_server0.api_server01"
		case "rw-core":
			affinity_group, ok := pod.Labels["affinity-group"]
			if !ok {
				log.Printf("rwcore %s lacks affinity-group label", pod.Name)
				continue
			}
			affinity_group_core_id, ok := pod.Labels["affinity-group-core-id"]
			if !ok {
				log.Printf("rwcore %s lacks affinity-group-core-id label", pod.Name)
				continue
			}
			arouter_name = "vcore" + affinity_group + ".vcore" + affinity_group + affinity_group_core_id
		case "ro-core":
			/*
			 * Assumes a single rocore for now.
			 * TODO: Make labeling changes in charts to be able to derive name from labels
			 */
			arouter_name = "ro_vcore0.ro_vcore01"
		default:
			// skip this pod as it's not relevant
			continue
		}

		// Multiple ways to identify the component

		// 1) The pod name. One pod name maps to exactly one pod.

		arouter_to_kube[arouter_name] = pod.Name
		MapListAppend(kube_to_arouter, pod.Name, arouter_name)

		// 2) The kubernetes component name. A single component (i.e. "core") may map to multiple pods.

		component, ok := pod.Labels["app.kubernetes.io/component"]
		if ok {
			MapListAppend(kube_to_arouter, component, arouter_name)
		}

		// 3) The voltha app label. A single app (i.e. "rwcore") may map to multiple pods.

		MapListAppend(kube_to_arouter, app, arouter_name)

	}

	return kube_to_arouter, arouter_to_kube, nil
}

func (options *SetLogLevelOpts) Execute(args []string) error {
	if len(options.Args.Component) == 0 {
		return fmt.Errorf("Please specify at least one component")
	}

	kube_to_arouter, arouter_to_kube, err := BuildKubernetesNameMap()
	if err != nil {
		return err
	}

	var output []SetLogLevelOutput

	// Validate component names, throw error now to avoid doing partial work
	err = ValidateComponentNames(kube_to_arouter, options.Args.Component)
	if err != nil {
		return err
	}

	// Validate and map the logLevel string to an integer, throw error now to avoid doing partial work
	intLogLevel, err := LogLevelStringToInt(options.Args.Level)
	if err != nil {
		return err
	}

	for _, kubeComponentName := range options.Args.Component {
		var descriptor grpcurl.DescriptorSource
		var conn *grpc.ClientConn
		var method string

		componentNameList := kube_to_arouter[kubeComponentName]

		for _, componentName := range componentNameList {
			conn, err = NewConnection()
			if err != nil {
				return err
			}
			defer conn.Close()
			if strings.HasPrefix(componentName, "api_server") {
				// apiserver's UpdateLogLevel is in the afrouter.Configuration gRPC package
				descriptor, method, err = GetMethod("apiserver-update-log-level")
			} else {
				descriptor, method, err = GetMethod("update-log-level")
			}
			if err != nil {
				return err
			}

			ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
			defer cancel()

			ll := make(map[string]interface{})
			ll["component_name"] = componentName
			ll["package_name"] = options.Package
			ll["level"] = intLogLevel

			h := &RpcEventHandler{
				Fields: map[string]map[string]interface{}{"common.Logging": ll},
			}
			err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
			if err != nil {
				return err
			}

			if h.Status != nil && h.Status.Err() != nil {
				output = append(output, SetLogLevelOutput{ComponentName: arouter_to_kube[componentName], Status: "Failure", Error: h.Status.Err().Error()})
				continue
			}

			output = append(output, SetLogLevelOutput{ComponentName: arouter_to_kube[componentName], Status: "Success"})
		}
	}

	outputFormat := CharReplacer.Replace(options.Format)
	if outputFormat == "" {
		outputFormat = DEFAULT_SETLOGLEVEL_FORMAT
	}

	result := CommandResult{
		Format:    format.Format(outputFormat),
		OutputAs:  toOutputType(options.OutputAs),
		NameLimit: options.NameLimit,
		Data:      output,
	}

	GenerateOutput(&result)
	return nil
}

func (options *GetLogLevelsOpts) Execute(args []string) error {
	if len(options.Args.Component) == 0 {
		return fmt.Errorf("Please specify at least one component")
	}

	kube_to_arouter, arouter_to_kube, err := BuildKubernetesNameMap()
	if err != nil {
		return err
	}

	var data []model.LogLevel

	// Validate component names, throw error now to avoid doing partial work
	err = ValidateComponentNames(kube_to_arouter, options.Args.Component)
	if err != nil {
		return err
	}

	for _, kubeComponentName := range options.Args.Component {
		var descriptor grpcurl.DescriptorSource
		var conn *grpc.ClientConn
		var method string

		componentNameList := kube_to_arouter[kubeComponentName]

		for _, componentName := range componentNameList {
			conn, err = NewConnection()
			if err != nil {
				return err
			}
			defer conn.Close()
			if strings.HasPrefix(componentName, "api_server") {
				// apiserver's UpdateLogLevel is in the afrouter.Configuration gRPC package
				descriptor, method, err = GetMethod("apiserver-get-log-levels")
			} else {
				descriptor, method, err = GetMethod("get-log-levels")
			}
			if err != nil {
				return err
			}

			ctx, cancel := context.WithTimeout(context.Background(), GlobalConfig.Grpc.Timeout)
			defer cancel()

			ll := make(map[string]interface{})
			ll["component_name"] = componentName

			h := &RpcEventHandler{
				Fields: map[string]map[string]interface{}{"common.LoggingComponent": ll},
			}
			err = grpcurl.InvokeRPC(ctx, descriptor, conn, method, []string{}, h, h.GetParams)
			if err != nil {
				return err
			}

			if h.Status != nil && h.Status.Err() != nil {
				return h.Status.Err()
			}

			d, err := dynamic.AsDynamicMessage(h.Response)
			if err != nil {
				return err
			}
			items, err := d.TryGetFieldByName("items")
			if err != nil {
				return err
			}

			for _, item := range items.([]interface{}) {
				logLevel := model.LogLevel{}
				logLevel.PopulateFrom(item.(*dynamic.Message))
				logLevel.ComponentName = arouter_to_kube[logLevel.ComponentName]

				data = append(data, logLevel)
			}
		}
	}

	outputFormat := CharReplacer.Replace(options.Format)
	if outputFormat == "" {
		outputFormat = DEFAULT_LOGLEVELS_FORMAT
	}

	result := CommandResult{
		Format:    format.Format(outputFormat),
		Filter:    options.Filter,
		OrderBy:   options.OrderBy,
		OutputAs:  toOutputType(options.OutputAs),
		NameLimit: options.NameLimit,
		Data:      data,
	}
	GenerateOutput(&result)
	return nil
}

func (options *ListLogLevelsOpts) Execute(args []string) error {
	var getOptions GetLogLevelsOpts
	var podNames []string

	_, arouter_to_kube, err := BuildKubernetesNameMap()
	if err != nil {
		return err
	}

	for _, podName := range arouter_to_kube {
		podNames = append(podNames, podName)
	}

	// Just call GetLogLevels with a list of podnames that includes everything relevant.

	getOptions.ListOutputOptions = options.ListOutputOptions
	getOptions.Args.Component = podNames

	return getOptions.Execute(args)
}
