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

	"github.com/spf13/cobra"

	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"

	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
	"github.com/apache/camel-k/pkg/util/indentedwriter"
)

func newDescribeKitCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *describeKitCommandOptions) {
	options := describeKitCommandOptions{
		rootCmdOptions,
	}

	cmd := cobra.Command{
		Use:     "kit",
		Short:   "Describe an Integration Kit",
		Long:    `Describe an Integration Kit.`,
		PreRunE: decode(&options),
		RunE: func(_ *cobra.Command, args []string) error {
			if err := options.validate(args); err != nil {
				return err
			}
			if err := options.run(args); err != nil {
				fmt.Println(err.Error())
			}

			return nil
		},
	}

	return &cmd, &options
}

type describeKitCommandOptions struct {
	*RootCmdOptions
}

func (command *describeKitCommandOptions) validate(args []string) error {
	if len(args) != 1 {
		return errors.New("describe expects a kit name argument")
	}
	return nil
}

func (command *describeKitCommandOptions) run(args []string) error {
	c, err := command.GetCmdClient()
	if err != nil {
		return err
	}

	kit := v1.NewIntegrationKit(command.Namespace, args[0])
	kitKey := k8sclient.ObjectKey{
		Namespace: command.Namespace,
		Name:      args[0],
	}

	if err := c.Get(command.Context, kitKey, &kit); err == nil {
		fmt.Print(command.describeIntegrationKit(kit))
	} else {
		fmt.Printf("IntegrationKit '%s' does not exist.\n", args[0])
	}

	return nil
}

func (command *describeKitCommandOptions) describeIntegrationKit(kit v1.IntegrationKit) (string, error) {
	return indentedwriter.IndentedString(func(out io.Writer) error {
		w := indentedwriter.NewWriter(out)

		describeObjectMeta(w, kit.ObjectMeta)

		w.Write(0, "Phase:\t%s\n", kit.Status.Phase)
		w.Write(0, "Runtime Version:\t%s\n", kit.Status.RuntimeVersion)
		w.Write(0, "Image:\t%s\n", kit.Status.Image)
		w.Write(0, "Version:\t%s\n", kit.Status.Version)

		if len(kit.Status.Artifacts) > 0 {
			w.Write(0, "Artifacts:\t\n")
			for _, artifact := range kit.Status.Artifacts {
				w.Write(1, "%s\n", artifact.ID)
			}
		}

		if len(kit.Spec.Configuration) > 0 {
			w.Write(0, "Configuration:\n")
			for _, config := range kit.Spec.Configuration {
				w.Write(1, "Type:\t%s\n", config.Type)
				w.Write(1, "Value:\t%s\n", config.Value)
			}
		}

		if len(kit.Spec.Dependencies) > 0 {
			w.Write(0, "Dependencies:\t\n")
			for _, dependency := range kit.Spec.Dependencies {
				w.Write(1, "%s\n", dependency)
			}
		}

		if len(kit.Spec.Repositories) > 0 {
			w.Write(0, "Repositories:\n")
			for _, repository := range kit.Spec.Repositories {
				w.Write(1, "%s\n", repository)
			}
		}

		return describeTraits(w, kit.Spec.Traits)
	})
}
