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

	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"

	"k8s.io/api/extensions/v1beta1"
	"k8s.io/apimachinery/pkg/util/intstr"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type ingressTrait struct {
	BaseTrait `property:",squash"`
	Host      string `property:"host"`
	Auto      *bool  `property:"auto"`
}

func newIngressTrait() *ingressTrait {
	return &ingressTrait{
		BaseTrait: newBaseTrait("ingress"),
		Host:      "",
	}
}

func (t *ingressTrait) Configure(e *Environment) (bool, error) {
	if t.Enabled != nil && !*t.Enabled {
		e.Integration.Status.SetCondition(
			v1alpha1.IntegrationConditionExposureAvailable,
			corev1.ConditionFalse,
			v1alpha1.IntegrationConditionIngressNotAvailableReason,
			"explicitly disabled",
		)
		return false, nil
	}

	if !e.IntegrationInPhase(v1alpha1.IntegrationPhaseDeploying) {
		return false, nil
	}

	if t.Auto == nil || *t.Auto {
		hasService := e.Resources.GetUserServiceForIntegration(e.Integration) != nil
		hasHost := t.Host != ""
		enabled := hasService && hasHost

		if !enabled {
			e.Integration.Status.SetCondition(
				v1alpha1.IntegrationConditionExposureAvailable,
				corev1.ConditionFalse,
				v1alpha1.IntegrationConditionIngressNotAvailableReason,
				"no host or service defined",
			)

			return false, nil
		}
	}

	if t.Host == "" {
		e.Integration.Status.SetCondition(
			v1alpha1.IntegrationConditionExposureAvailable,
			corev1.ConditionFalse,
			v1alpha1.IntegrationConditionIngressNotAvailableReason,
			"no host defined",
		)

		return false, errors.New("cannot Apply ingress trait: no host defined")
	}

	return true, nil
}

func (t *ingressTrait) Apply(e *Environment) error {
	service := e.Resources.GetUserServiceForIntegration(e.Integration)
	if service == nil {
		return errors.New("cannot Apply ingress trait: no target service")
	}

	ingress := v1beta1.Ingress{
		TypeMeta: metav1.TypeMeta{
			Kind:       "Ingress",
			APIVersion: v1beta1.SchemeGroupVersion.String(),
		},
		ObjectMeta: metav1.ObjectMeta{
			Name:      service.Name,
			Namespace: service.Namespace,
		},
		Spec: v1beta1.IngressSpec{
			Backend: &v1beta1.IngressBackend{
				ServiceName: service.Name,
				ServicePort: intstr.FromString("http"),
			},
			Rules: []v1beta1.IngressRule{
				{
					Host: t.Host,
				},
			},
		},
	}

	e.Resources.Add(&ingress)

	message := fmt.Sprintf("%s(%s) -> %s(%s)",
		ingress.Name,
		t.Host,
		ingress.Spec.Backend.ServiceName,
		ingress.Spec.Backend.ServicePort.String())

	e.Integration.Status.SetCondition(
		v1alpha1.IntegrationConditionExposureAvailable,
		corev1.ConditionTrue,
		v1alpha1.IntegrationConditionIngressAvailableReason,
		message,
	)

	return nil
}
