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

import (
	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
	monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1"
	routev1 "github.com/openshift/api/route/v1"
	appsv1 "k8s.io/api/apps/v1"
	"k8s.io/api/batch/v1beta1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	eventing "knative.dev/eventing/pkg/apis/eventing/v1alpha1"
	serving "knative.dev/serving/pkg/apis/serving/v1"
)

// A Collection is a container of Kubernetes resources
type Collection struct {
	items []runtime.Object
}

// NewCollection creates a new empty collection
func NewCollection(objects ...runtime.Object) *Collection {
	collection := Collection{
		items: make([]runtime.Object, 0, len(objects)),
	}

	collection.items = append(collection.items, objects...)

	return &collection
}

// Size returns the number of resources belonging to the collection
func (c *Collection) Size() int {
	return len(c.items)
}

// Items returns all resources belonging to the collection
func (c *Collection) Items() []runtime.Object {
	return c.items
}

// AsKubernetesList returns all resources wrapped in a Kubernetes list
func (c *Collection) AsKubernetesList() *corev1.List {
	lst := corev1.List{
		TypeMeta: metav1.TypeMeta{
			Kind:       "List",
			APIVersion: "v1",
		},
		Items: make([]runtime.RawExtension, 0, len(c.items)),
	}
	for _, res := range c.items {
		raw := runtime.RawExtension{
			Object: res,
		}
		lst.Items = append(lst.Items, raw)
	}
	return &lst
}

// Add adds a resource to the collection
func (c *Collection) Add(resource runtime.Object) {
	if resource != nil {
		c.items = append(c.items, resource)
	}
}

// AddAll adds all resources to the collection
func (c *Collection) AddAll(resource []runtime.Object) {
	c.items = append(c.items, resource...)
}

// VisitDeployment executes the visitor function on all Deployment resources
func (c *Collection) VisitDeployment(visitor func(*appsv1.Deployment)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*appsv1.Deployment); ok {
			visitor(conv)
		}
	})
}

// VisitDeploymentE executes the visitor function on all Deployment resources
func (c *Collection) VisitDeploymentE(visitor func(*appsv1.Deployment) error) error {
	return c.VisitE(func(res runtime.Object) error {
		if conv, ok := res.(*appsv1.Deployment); ok {
			return visitor(conv)
		}

		return nil
	})
}

// GetDeployment returns a Deployment that matches the given function
func (c *Collection) GetDeployment(filter func(*appsv1.Deployment) bool) *appsv1.Deployment {
	var retValue *appsv1.Deployment
	c.VisitDeployment(func(re *appsv1.Deployment) {
		if filter(re) {
			retValue = re
		}
	})
	return retValue
}

// GetDeploymentForIntegration returns a Deployment for the given integration
func (c *Collection) GetDeploymentForIntegration(integration *v1.Integration) *appsv1.Deployment {
	if integration == nil {
		return nil
	}

	return c.GetDeployment(func(d *appsv1.Deployment) bool {
		return d.ObjectMeta.Labels["camel.apache.org/integration"] == integration.Name
	})
}

// HasDeployment returns true if a deployment matching the given condition is present
func (c *Collection) HasDeployment(filter func(*appsv1.Deployment) bool) bool {
	return c.GetDeployment(filter) != nil
}

// RemoveDeployment removes and returns a Deployment that matches the given function
func (c *Collection) RemoveDeployment(filter func(*appsv1.Deployment) bool) *appsv1.Deployment {
	res := c.Remove(func(res runtime.Object) bool {
		if conv, ok := res.(*appsv1.Deployment); ok {
			return filter(conv)
		}
		return false
	})
	if res == nil {
		return nil
	}
	return res.(*appsv1.Deployment)
}

// VisitConfigMap executes the visitor function on all ConfigMap resources
func (c *Collection) VisitConfigMap(visitor func(*corev1.ConfigMap)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*corev1.ConfigMap); ok {
			visitor(conv)
		}
	})
}

// GetConfigMap returns a ConfigMap that matches the given function
func (c *Collection) GetConfigMap(filter func(*corev1.ConfigMap) bool) *corev1.ConfigMap {
	var retValue *corev1.ConfigMap
	c.VisitConfigMap(func(re *corev1.ConfigMap) {
		if filter(re) {
			retValue = re
		}
	})
	return retValue
}

// RemoveConfigMap removes and returns a ConfigMap that matches the given function
func (c *Collection) RemoveConfigMap(filter func(*corev1.ConfigMap) bool) *corev1.ConfigMap {
	res := c.Remove(func(res runtime.Object) bool {
		if conv, ok := res.(*corev1.ConfigMap); ok {
			return filter(conv)
		}
		return false
	})
	if res == nil {
		return nil
	}
	return res.(*corev1.ConfigMap)
}

// VisitService executes the visitor function on all Service resources
func (c *Collection) VisitService(visitor func(*corev1.Service)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*corev1.Service); ok {
			visitor(conv)
		}
	})
}

// GetService returns a Service that matches the given function
func (c *Collection) GetService(filter func(*corev1.Service) bool) *corev1.Service {
	var retValue *corev1.Service
	c.VisitService(func(re *corev1.Service) {
		if filter(re) {
			retValue = re
		}
	})
	return retValue
}

// GetUserServiceForIntegration returns a user Service for the given integration
func (c *Collection) GetUserServiceForIntegration(integration *v1.Integration) *corev1.Service {
	if integration == nil {
		return nil
	}
	return c.GetService(func(s *corev1.Service) bool {
		return s.ObjectMeta.Labels != nil &&
			s.ObjectMeta.Labels["camel.apache.org/integration"] == integration.Name &&
			s.ObjectMeta.Labels["camel.apache.org/service.type"] == v1.ServiceTypeUser
	})
}

// GetServiceForIntegration returns a user Service for the given integration
func (c *Collection) GetServiceForIntegration(integration *v1.Integration) *corev1.Service {
	if integration == nil {
		return nil
	}
	return c.GetService(func(s *corev1.Service) bool {
		return s.ObjectMeta.Labels != nil && s.ObjectMeta.Labels["camel.apache.org/integration"] == integration.Name
	})
}

// GetKnativeService returns a knative Service that matches the given function
func (c *Collection) GetKnativeService(filter func(*serving.Service) bool) *serving.Service {
	var retValue *serving.Service
	c.VisitKnativeService(func(re *serving.Service) {
		if filter(re) {
			retValue = re
		}
	})
	return retValue
}

// VisitRoute executes the visitor function on all Route resources
func (c *Collection) VisitRoute(visitor func(*routev1.Route)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*routev1.Route); ok {
			visitor(conv)
		}
	})
}

// GetRoute returns a Route that matches the given function
func (c *Collection) GetRoute(filter func(*routev1.Route) bool) *routev1.Route {
	var retValue *routev1.Route
	c.VisitRoute(func(re *routev1.Route) {
		if filter(re) {
			retValue = re
		}
	})
	return retValue
}

// VisitCronJob executes the visitor function on all CronJob resources
func (c *Collection) VisitCronJob(visitor func(*v1beta1.CronJob)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*v1beta1.CronJob); ok {
			visitor(conv)
		}
	})
}

// VisitCronJobE executes the visitor function on all CronJob resources
func (c *Collection) VisitCronJobE(visitor func(*v1beta1.CronJob) error) error {
	return c.VisitE(func(res runtime.Object) error {
		if conv, ok := res.(*v1beta1.CronJob); ok {
			return visitor(conv)
		}

		return nil
	})
}

// VisitKnativeService executes the visitor function on all Knative serving Service resources
func (c *Collection) VisitKnativeService(visitor func(*serving.Service)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*serving.Service); ok {
			visitor(conv)
		}
	})
}

// VisitKnativeServiceE executes the visitor function on all Knative serving Service resources
func (c *Collection) VisitKnativeServiceE(visitor func(*serving.Service) error) error {
	return c.VisitE(func(res runtime.Object) error {
		if conv, ok := res.(*serving.Service); ok {
			return visitor(conv)
		}

		return nil
	})
}

// VisitKnativeTrigger executes the visitor function on all Knative eventing Trigger resources
func (c *Collection) VisitKnativeTrigger(visitor func(trigger *eventing.Trigger)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*eventing.Trigger); ok {
			visitor(conv)
		}
	})
}

// HasKnativeTrigger returns true if a Knative trigger respecting filter is found
func (c *Collection) HasKnativeTrigger(filter func(trigger *eventing.Trigger) bool) bool {
	var retValue *bool
	c.VisitKnativeTrigger(func(re *eventing.Trigger) {
		if filter(re) {
			found := true
			retValue = &found
		}
	})
	return retValue != nil && *retValue
}

// GetContainer --
func (c *Collection) GetContainer(filter func(container *corev1.Container) bool) *corev1.Container {
	var retValue *corev1.Container

	c.VisitContainer(func(container *corev1.Container) {
		if filter(container) {
			retValue = container
		}
	})

	return retValue
}

// GetContainerByName --
func (c *Collection) GetContainerByName(name string) *corev1.Container {
	return c.GetContainer(func(c *corev1.Container) bool {
		return c.Name == name
	})
}

// VisitContainer executes the visitor function on all Containers inside deployments or other resources
func (c *Collection) VisitContainer(visitor func(container *corev1.Container)) {
	c.VisitDeployment(func(d *appsv1.Deployment) {
		for idx := range d.Spec.Template.Spec.Containers {
			cntref := &d.Spec.Template.Spec.Containers[idx]
			visitor(cntref)
		}
	})
	c.VisitKnativeConfigurationSpec(func(cs *serving.ConfigurationSpec) {
		for id := range cs.Template.Spec.Containers {
			cntref := &cs.Template.Spec.Containers[id]
			visitor(cntref)
		}
	})
	c.VisitCronJob(func(c *v1beta1.CronJob) {
		for idx := range c.Spec.JobTemplate.Spec.Template.Spec.Containers {
			cntref := &c.Spec.JobTemplate.Spec.Template.Spec.Containers[idx]
			visitor(cntref)
		}
	})
}

// VisitPodSpec executes the visitor function on all PodSpec inside deployments or other resources
func (c *Collection) VisitPodSpec(visitor func(container *corev1.PodSpec)) {
	c.VisitDeployment(func(d *appsv1.Deployment) {
		visitor(&d.Spec.Template.Spec)
	})
	c.VisitKnativeConfigurationSpec(func(cs *serving.ConfigurationSpec) {
		visitor(&cs.Template.Spec.PodSpec)
	})
	c.VisitCronJob(func(d *v1beta1.CronJob) {
		visitor(&d.Spec.JobTemplate.Spec.Template.Spec)
	})
}

// VisitKnativeConfigurationSpec executes the visitor function on all knative ConfigurationSpec inside serving Services
func (c *Collection) VisitKnativeConfigurationSpec(visitor func(container *serving.ConfigurationSpec)) {
	c.VisitKnativeService(func(s *serving.Service) {
		visitor(&s.Spec.ConfigurationSpec)
	})
}

// VisitMetaObject executes the visitor function on all meta.Object resources
func (c *Collection) VisitMetaObject(visitor func(metav1.Object)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(metav1.Object); ok {
			visitor(conv)
		}
	})
}

// Visit executes the visitor function on all resources
func (c *Collection) Visit(visitor func(runtime.Object)) {
	for _, res := range c.items {
		visitor(res)
	}
}

// VisitE executes the visitor function on all resources breaking if the visitor function
// returns an error
func (c *Collection) VisitE(visitor func(runtime.Object) error) error {
	for _, res := range c.items {
		if err := visitor(res); err != nil {
			return err
		}
	}

	return nil
}

// Remove removes the given element from the collection and returns it
func (c *Collection) Remove(selector func(runtime.Object) bool) runtime.Object {
	for idx, res := range c.items {
		if selector(res) {
			c.items = append(c.items[0:idx], c.items[idx+1:]...)
			return res
		}
	}
	return nil
}

// VisitServiceMonitor ---
func (c *Collection) VisitServiceMonitor(visitor func(*monitoringv1.ServiceMonitor)) {
	c.Visit(func(res runtime.Object) {
		if conv, ok := res.(*monitoringv1.ServiceMonitor); ok {
			visitor(conv)
		}
	})
}

// GetServiceMonitor ---
func (c *Collection) GetServiceMonitor(filter func(*monitoringv1.ServiceMonitor) bool) *monitoringv1.ServiceMonitor {
	var retValue *monitoringv1.ServiceMonitor
	c.VisitServiceMonitor(func(serviceMonitor *monitoringv1.ServiceMonitor) {
		if filter(serviceMonitor) {
			retValue = serviceMonitor
		}
	})
	return retValue
}
