/*
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 (
	"sort"
	"strconv"

	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
	"github.com/apache/camel-k/pkg/util"
	"k8s.io/apimachinery/pkg/util/intstr"

	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
)

type probesTrait struct {
	BaseTrait `property:",squash"`

	BindHost                  string `property:"bind-host"`
	BindPort                  int    `property:"bind-port"`
	Path                      string `property:"path"`
	LivenessInitialDelay      int32  `property:"liveness-initial-delay"`
	LivenessTimeout           int32  `property:"liveness-timeout"`
	LivenessPeriod            int32  `property:"liveness-period"`
	LivenessSuccessThreshold  int32  `property:"liveness-success-threshold"`
	LivenessFailureThreshold  int32  `property:"liveness-failure-threshold"`
	ReadinessInitialDelay     int32  `property:"readiness-initial-delay"`
	ReadinessTimeout          int32  `property:"readiness-timeout"`
	ReadinessPeriod           int32  `property:"readiness-period"`
	ReadinessSuccessThreshold int32  `property:"readiness-success-threshold"`
	ReadinessFailureThreshold int32  `property:"readiness-failure-threshold"`
}

func newProbesTrait() *probesTrait {
	return &probesTrait{
		BaseTrait: newBaseTrait("probes"),
		BindHost:  "0.0.0.0",
		BindPort:  8081,
		Path:      "/health",
	}
}

func (t *probesTrait) Configure(e *Environment) (bool, error) {
	if t.Enabled != nil && *t.Enabled {
		return e.IntegrationInPhase(v1alpha1.IntegrationPhaseInitialization) || e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying), nil
	}

	return false, nil
}

func (t *probesTrait) Apply(e *Environment) error {
	if e.IntegrationInPhase(v1alpha1.IntegrationPhaseInitialization) {
		util.StringSliceUniqueAdd(&e.Integration.Status.Dependencies, "mvn:org.apache.camel.k/camel-k-runtime-health")

		// sort the dependencies to get always the same list if they don't change
		sort.Strings(e.Integration.Status.Dependencies)

		e.Integration.Status.Configuration = append(e.Integration.Status.Configuration,
			//
			// TODO: At the moment the servlet engine is used only for health but we need to
			//       have a dedicated servlet trait and maybe an option to create a dedicated
			//       server for management stuffs like health
			//
			v1alpha1.ConfigurationSpec{Type: "property", Value: "customizer.servlet.enabled=true"},
			v1alpha1.ConfigurationSpec{Type: "property", Value: "customizer.servlet.bindHost=" + t.BindHost},
			v1alpha1.ConfigurationSpec{Type: "property", Value: "customizer.servlet.bindPort=" + strconv.Itoa(t.BindPort)},
			v1alpha1.ConfigurationSpec{Type: "property", Value: "customizer.health.enabled=true"},
			v1alpha1.ConfigurationSpec{Type: "property", Value: "customizer.health.path=" + t.Path},
		)
	}

	if e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying) {
		e.Resources.VisitDeployment(func(deployment *appsv1.Deployment) {
			if len(deployment.Spec.Template.Spec.Containers) != 1 {
				return
			}

			deployment.Spec.Template.Spec.Containers[0].LivenessProbe = t.newLivenessProbe()
			deployment.Spec.Template.Spec.Containers[0].ReadinessProbe = t.newReadinessProbe()
		})
	}

	return nil
}

func (t *probesTrait) newLivenessProbe() *corev1.Probe {
	p := corev1.Probe{
		Handler: corev1.Handler{
			HTTPGet: &corev1.HTTPGetAction{
				Port: intstr.FromInt(t.BindPort),
				Path: t.Path,
			},
		},
	}

	p.InitialDelaySeconds = t.LivenessInitialDelay
	p.TimeoutSeconds = t.LivenessTimeout
	p.PeriodSeconds = t.LivenessPeriod
	p.SuccessThreshold = t.LivenessSuccessThreshold
	p.FailureThreshold = t.LivenessFailureThreshold

	return &p
}

func (t *probesTrait) newReadinessProbe() *corev1.Probe {
	p := corev1.Probe{
		Handler: corev1.Handler{
			HTTPGet: &corev1.HTTPGetAction{
				Port: intstr.FromInt(t.BindPort),
				Path: t.Path,
			},
		},
	}

	p.InitialDelaySeconds = t.ReadinessInitialDelay
	p.TimeoutSeconds = t.ReadinessTimeout
	p.PeriodSeconds = t.ReadinessPeriod
	p.SuccessThreshold = t.ReadinessSuccessThreshold
	p.FailureThreshold = t.ReadinessFailureThreshold

	return &p
}
