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

import (
	"github.com/pkg/errors"

	"k8s.io/apimachinery/pkg/types"

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

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

// The deployer trait can be used to explicitly select the kind of high level resource that
// will deploy the integration.
//
// +camel-k:trait=deployer
type deployerTrait struct {
	BaseTrait `property:",squash"`
	// Allows to explicitly select the desired deployment kind between `deployment`, `cron-job` or `knative-service` when creating the resources for running the integration.
	Kind string `property:"kind"`
}

var _ ControllerStrategySelector = &deployerTrait{}

func newDeployerTrait() Trait {
	return &deployerTrait{
		BaseTrait: NewBaseTrait("deployer", 900),
	}
}

func (t *deployerTrait) Configure(e *Environment) (bool, error) {
	return e.IntegrationInPhase(
		v1.IntegrationPhaseNone,
		v1.IntegrationPhaseWaitingForPlatform,
		v1.IntegrationPhaseInitialization,
		v1.IntegrationPhaseBuildingKit,
		v1.IntegrationPhaseResolvingKit,
		v1.IntegrationPhaseDeploying,
		v1.IntegrationPhaseRunning,
	), nil
}

func (t *deployerTrait) Apply(e *Environment) error {
	switch e.Integration.Status.Phase {

	case v1.IntegrationPhaseNone, v1.IntegrationPhaseWaitingForPlatform, v1.IntegrationPhaseInitialization, v1.IntegrationPhaseDeploying:
		// Register a post action that updates the resources generated by the traits
		e.PostActions = append(e.PostActions, func(env *Environment) error {
			if err := kubernetes.ReplaceResources(env.C, env.Client, env.Resources.Items()); err != nil {
				return errors.Wrap(err, "error during replace resource")
			}
			return nil
		})

	case v1.IntegrationPhaseBuildingKit, v1.IntegrationPhaseResolvingKit:
		if e.IntegrationKitInPhase(v1.IntegrationKitPhaseReady) {
			e.PostProcessors = append(e.PostProcessors, func(environment *Environment) error {
				// trigger integration deploy
				e.Integration.Status.Phase = v1.IntegrationPhaseDeploying
				return nil
			})
		}

	case v1.IntegrationPhaseRunning:
		// Register a post action that patches the resources generated by the traits
		e.PostActions = append(e.PostActions, func(env *Environment) error {
			for _, resource := range env.Resources.Items() {
				key, err := client.ObjectKeyFromObject(resource)
				if err != nil {
					return err
				}

				object := resource.DeepCopyObject()
				err = env.Client.Get(env.C, key, object)
				if err != nil {
					return err
				}

				p, err := patch.PositiveMergePatch(object, resource)
				if err != nil {
					return err
				} else if len(p) == 0 {
					// Avoid triggering a patch request for nothing
					continue
				}

				err = env.Client.Patch(env.C, resource, client.RawPatch(types.MergePatchType, p))
				if err != nil {
					return errors.Wrap(err, "error during patch resource")
				}
			}
			return nil
		})
	}

	return nil
}

func (t *deployerTrait) SelectControllerStrategy(e *Environment) (*ControllerStrategy, error) {
	if t.Enabled != nil && !*t.Enabled {
		return nil, nil
	}
	if t.Kind != "" {
		strategy := ControllerStrategy(t.Kind)
		return &strategy, nil
	}
	return nil, nil
}

func (t *deployerTrait) ControllerStrategySelectorOrder() int {
	return 0
}

// IsPlatformTrait overrides base class method
func (t *deployerTrait) IsPlatformTrait() bool {
	return true
}

// RequiresIntegrationPlatform overrides base class method
func (t *deployerTrait) RequiresIntegrationPlatform() bool {
	return false
}
