/*
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"
	"strings"

	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
	"github.com/apache/camel-k/pkg/trait"
	"github.com/apache/camel-k/pkg/util"
	"github.com/apache/camel-k/pkg/util/kubernetes"

	"github.com/spf13/cobra"

	k8serrors "k8s.io/apimachinery/pkg/api/errors"
	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
)

func newKitCreateCmd(rootCmdOptions *RootCmdOptions) (*cobra.Command, *kitCreateCommandOptions) {
	options := kitCreateCommandOptions{
		RootCmdOptions: rootCmdOptions,
	}

	cmd := cobra.Command{
		Use:     "create <name>",
		Short:   "Create an Integration Kit",
		Long:    `Create an Integration Kit.`,
		Args:    options.validateArgs,
		PreRunE: decode(&options),
		RunE:    options.run,
	}

	cmd.Flags().String("image", "", "Image used to create the kit")
	cmd.Flags().StringArrayP("dependency", "d", nil, "Add a dependency")
	cmd.Flags().StringArrayP("property", "p", nil, "Add a camel property")
	cmd.Flags().StringArray("configmap", nil, "Add a ConfigMap")
	cmd.Flags().StringArray("secret", nil, "Add a Secret")
	cmd.Flags().StringArray("repository", nil, "Add a maven repository")
	cmd.Flags().StringArrayP("trait", "t", nil, "Configure a trait. E.g. \"-t service.enabled=false\"")

	// completion support
	configureKnownCompletions(&cmd)

	return &cmd, &options
}

type kitCreateCommandOptions struct {
	*RootCmdOptions

	Image        string   `mapstructure:"image"`
	Dependencies []string `mapstructure:"dependencies"`
	Properties   []string `mapstructure:"properties"`
	Configmaps   []string `mapstructure:"configmaps"`
	Secrets      []string `mapstructure:"secrets"`
	Repositories []string `mapstructure:"repositories"`
	Traits       []string `mapstructure:"traits"`
}

func (command *kitCreateCommandOptions) validateArgs(_ *cobra.Command, args []string) error {
	if len(args) != 1 {
		return errors.New("create expects a single name argument")
	}

	return nil
}

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

	catalog := trait.NewCatalog(command.Context, c)
	tp := catalog.ComputeTraitsProperties()
	for _, t := range command.Traits {
		kv := strings.SplitN(t, "=", 2)

		if !util.StringSliceExists(tp, kv[0]) {
			fmt.Printf("Error: %s is not a valid trait property\n", t)
			return nil
		}
	}

	ctx := v1.NewIntegrationKit(command.Namespace, args[0])
	key := k8sclient.ObjectKey{
		Namespace: command.Namespace,
		Name:      args[0],
	}
	if err := c.Get(command.Context, key, &ctx); err == nil {
		// the integration kit already exists, let's check that it is
		// not a platform one which is supposed to be "read only"

		if ctx.Labels["camel.apache.org/kit.type"] == v1.IntegrationKitTypePlatform {
			fmt.Printf("integration kit \"%s\" is not editable\n", ctx.Name)
			return nil
		}
	}

	ctx = v1.NewIntegrationKit(command.Namespace, kubernetes.SanitizeName(args[0]))
	ctx.Labels = map[string]string{
		"camel.apache.org/kit.type": v1.IntegrationKitTypeUser,
	}
	ctx.Spec = v1.IntegrationKitSpec{
		Dependencies:  make([]string, 0, len(command.Dependencies)),
		Configuration: make([]v1.ConfigurationSpec, 0),
		Repositories:  command.Repositories,
	}

	if command.Image != "" {
		//
		// if the Image is set, the kit do not require any build but
		// is be marked as external as the information about the classpath
		// is missing so it cannot be used as base for other Kits
		//
		ctx.Labels["camel.apache.org/kit.type"] = v1.IntegrationKitTypeExternal

		//
		// Set the Image to be used by the kit
		//
		ctx.Spec.Image = command.Image
	}
	for _, item := range command.Dependencies {
		switch {
		case strings.HasPrefix(item, "mvn:"):
			ctx.Spec.Dependencies = append(ctx.Spec.Dependencies, item)
		case strings.HasPrefix(item, "file:"):
			ctx.Spec.Dependencies = append(ctx.Spec.Dependencies, item)
		case strings.HasPrefix(item, "camel-quarkus-"):
			ctx.Spec.Dependencies = append(ctx.Spec.Dependencies, "camel-quarkus:"+strings.TrimPrefix(item, "camel-quarkus-"))
		case strings.HasPrefix(item, "camel-"):
			ctx.Spec.Dependencies = append(ctx.Spec.Dependencies, "camel:"+strings.TrimPrefix(item, "camel-"))
		}
	}

	for _, item := range command.Properties {
		ctx.Spec.Configuration = append(ctx.Spec.Configuration, v1.ConfigurationSpec{
			Type:  "property",
			Value: item,
		})
	}
	for _, item := range command.Configmaps {
		ctx.Spec.Configuration = append(ctx.Spec.Configuration, v1.ConfigurationSpec{
			Type:  "configmap",
			Value: item,
		})
	}
	for _, item := range command.Secrets {
		ctx.Spec.Configuration = append(ctx.Spec.Configuration, v1.ConfigurationSpec{
			Type:  "secret",
			Value: item,
		})
	}
	for _, item := range command.Traits {
		if err := command.configureTrait(&ctx, item); err != nil {
			return nil
		}
	}

	existed := false
	err = c.Create(command.Context, &ctx)
	if err != nil && k8serrors.IsAlreadyExists(err) {
		existed = true
		clone := ctx.DeepCopy()
		err = c.Get(command.Context, key, clone)
		if err != nil {
			fmt.Print(err.Error())
			return nil
		}
		ctx.ResourceVersion = clone.ResourceVersion
		err = c.Update(command.Context, &ctx)
	}

	if err != nil {
		fmt.Print(err.Error())
		return nil
	}

	if !existed {
		fmt.Printf("integration kit \"%s\" created\n", ctx.Name)
	} else {
		fmt.Printf("integration kit \"%s\" updated\n", ctx.Name)
	}

	return nil
}

func (*kitCreateCommandOptions) configureTrait(ctx *v1.IntegrationKit, config string) error {
	if ctx.Spec.Traits == nil {
		ctx.Spec.Traits = make(map[string]v1.TraitSpec)
	}

	parts := traitConfigRegexp.FindStringSubmatch(config)
	if len(parts) < 4 {
		return errors.New("unrecognized config format (expected \"<trait>.<prop>=<val>\"): " + config)
	}
	traitID := parts[1]
	prop := parts[2][1:]
	val := parts[3]

	spec, ok := ctx.Spec.Traits[traitID]
	if !ok {
		spec = v1.TraitSpec{
			Configuration: make(map[string]string),
		}
	}

	spec.Configuration[prop] = val
	ctx.Spec.Traits[traitID] = spec
	return nil
}
