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

import (
	"strings"

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

// StatefulSetOptions defines custom options for StatefulSets
type StatefulSetOptions struct {
	// Annotations to be added for the StatefulSet.
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`

	// Labels to be added for the StatefulSet.
	// +optional
	Labels map[string]string `json:"labels,omitempty"`

	// PodManagementPolicy defines the policy for creating pods under a stateful set.
	// Override the default value of Parallel.
	// This cannot be updated on an existing StatefulSet, the StatefulSet must be deleted and recreated for a change in this field to take effect.
	//
	// +optional
	// +kubebuilder:validation:Enum=OrderedReady;Parallel
	PodManagementPolicy appsv1.PodManagementPolicyType `json:"podManagementPolicy,omitempty"`
}

// DeploymentOptions defines custom options for Deployments
type DeploymentOptions struct {
	// Annotations to be added for the Deployment.
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`

	// Labels to be added for the Deployment.
	// +optional
	Labels map[string]string `json:"labels,omitempty"`
}

// PodOptions defines the common pod configuration for Pods, including when used
// in deployments, stateful-sets, etc.
type PodOptions struct {
	// The scheduling constraints on pods.
	// +optional
	Affinity *corev1.Affinity `json:"affinity,omitempty"`

	// Resources is the resource requirements for the default container.
	// +optional
	Resources corev1.ResourceRequirements `json:"resources,omitempty"`

	// Additional non-data volumes to load into the default container.
	// +optional
	Volumes []AdditionalVolume `json:"volumes,omitempty"`

	// PodSecurityContext is the security context for the pod.
	// +optional
	PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`

	// Additional environment variables to pass to the default container.
	// +optional
	EnvVariables []corev1.EnvVar `json:"envVars,omitempty"`

	// Annotations to be added for pods.
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`

	// Labels to be added for pods.
	// +optional
	Labels map[string]string `json:"labels,omitempty"`

	// Tolerations to be added for the StatefulSet.
	// +optional
	Tolerations []corev1.Toleration `json:"tolerations,omitempty"`

	// Node Selector to be added for the StatefulSet.
	// +optional
	NodeSelector map[string]string `json:"nodeSelector,omitempty"`

	// Liveness probe parameters
	// +optional
	LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"`

	// Readiness probe parameters
	// +optional
	ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`

	// Startup probe parameters
	// +optional
	StartupProbe *corev1.Probe `json:"startupProbe,omitempty"`

	// PriorityClassName for the pod
	// +optional
	PriorityClassName string `json:"priorityClassName,omitempty"`

	// Lifecycle for the main container
	// +optional
	Lifecycle *corev1.Lifecycle `json:"lifecycle,omitempty"`

	// Sidecar containers to run in the pod. These are in addition to the Solr Container
	// +optional
	SidecarContainers []corev1.Container `json:"sidecarContainers,omitempty"`

	// Additional init containers to run in the pod.
	// These will run along with the init container that sets up the "solr.xml".
	// +optional
	InitContainers []corev1.Container `json:"initContainers,omitempty"`

	// ImagePullSecrets to apply to the pod.
	// These are for init/sidecarContainers in addition to the imagePullSecret defined for the
	// solr image.
	// +optional
	ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`

	// Optional duration in seconds the pod needs to terminate gracefully.
	// +kubebuilder:validation:Minimum=10
	// +optional
	TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`

	// Optional Service Account to run the pod under.
	// +optional
	ServiceAccountName string `json:"serviceAccountName,omitempty"`

	// Optional PodSpreadTopologyConstraints to use when scheduling pods.
	// More information here: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
	//
	// Note: There is no need to provide a "labelSelector", as the operator will inject the labels for you if not provided.
	//
	// +patchMergeKey=topologyKey
	// +patchStrategy=merge
	// +listType=map
	// +listMapKey=topologyKey
	// +listMapKey=whenUnsatisfiable
	// +optional
	TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`

	// DefaultInitContainerResources are the resource requirements for the default init container(s) created by the Solr Operator, if any are created.
	// +optional
	DefaultInitContainerResources corev1.ResourceRequirements `json:"defaultInitContainerResources,omitempty"`
}

// ServiceOptions defines custom options for services
type ServiceOptions struct {
	// Annotations to be added for the Service.
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`

	// Labels to be added for the Service.
	// +optional
	Labels map[string]string `json:"labels,omitempty"`
}

// IngressOptions defines custom options for ingresses
type IngressOptions struct {
	// Annotations to be added for the Ingress.
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`

	// Labels to be added for the Ingress.
	// +optional
	Labels map[string]string `json:"labels,omitempty"`

	// IngressClassName is the name of the IngressClass cluster resource. The
	// associated IngressClass defines which controller will implement the resource.
	//
	// +kubebuilder:validation:Pattern:=[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*
	// +kubebuilder:validation:MinLength:=1
	// +kubebuilder:validation:MaxLength:=63
	// +optional
	IngressClassName *string `json:"ingressClassName,omitempty"`
}

// ConfigMapOptions defines custom options for configMaps
type ConfigMapOptions struct {
	// Annotations to be added for the ConfigMap.
	// +optional
	Annotations map[string]string `json:"annotations,omitempty"`

	// Labels to be added for the ConfigMap.
	// +optional
	Labels map[string]string `json:"labels,omitempty"`

	// Name of a user provided ConfigMap in the same namespace containing a custom solr.xml
	// +optional
	ProvidedConfigMap string `json:"providedConfigMap,omitempty"`
}

// AdditionalVolume provides information on additional volumes that should be loaded into pods
type AdditionalVolume struct {
	// Name of the volume
	Name string `json:"name"`

	// Source is the source of the Volume to be loaded into the solrCloud Pod
	Source corev1.VolumeSource `json:"source"`

	// DefaultContainerMount defines how to mount this volume into the default container.
	// If this volume is to be used only with sidecar or non-default init containers,
	// then this option is not necessary.
	// +optional
	DefaultContainerMount *corev1.VolumeMount `json:"defaultContainerMount,omitempty"`
}

// ContainerImage defines the fields needed for a Docker repository image. The
// format here matches the predominant format used in Helm charts.
type ContainerImage struct {
	// +optional
	Repository string `json:"repository,omitempty"`
	// +optional
	Tag string `json:"tag,omitempty"`
	// +optional
	PullPolicy corev1.PullPolicy `json:"pullPolicy,omitempty"`
	// +optional
	ImagePullSecret string `json:"imagePullSecret,omitempty"`
}

func (c *ContainerImage) withDefaults(repo string, version string, policy corev1.PullPolicy) (changed bool) {
	if c.Repository == "" && repo != "" {
		changed = true
		c.Repository = repo
	}
	if c.Tag == "" && version != "" {
		changed = true
		c.Tag = version
	}
	if c.PullPolicy == "" && policy != "" {
		changed = true
		c.PullPolicy = policy
	}
	return changed
}

func (c *ContainerImage) ToImageName() (name string) {
	return c.Repository + ":" + c.Tag
}

func ImageVersion(image string) (version string) {
	split := strings.Split(image, ":")
	if len(split) < 2 {
		return ""
	} else {
		return split[len(split)-1]
	}
}

// ZookeeperConnectionInfo is the information on how to connect to the Solr Zookeeper Cluster
type ZookeeperConnectionInfo struct {
	// The connection string to connect to the ensemble from within the Kubernetes cluster
	// +optional
	InternalConnectionString string `json:"internalConnectionString,omitempty"`

	// The connection string to connect to the ensemble from outside of the Kubernetes cluster
	// If external and no internal connection string is provided, the external cnx string will be used as the internal cnx string
	// +optional
	ExternalConnectionString *string `json:"externalConnectionString,omitempty"`

	// The ChRoot to connect solr at
	// +optional
	ChRoot string `json:"chroot,omitempty"`

	// ZooKeeper ACL to use when connecting with ZK.
	// This ACL should have ALL permission in the given chRoot.
	// +optional
	AllACL *ZookeeperACL `json:"acl,omitempty"`

	// ZooKeeper ACL to use when connecting with ZK for reading operations.
	// This ACL should have READ permission in the given chRoot.
	// +optional
	ReadOnlyACL *ZookeeperACL `json:"readOnlyAcl,omitempty"`
}

func (ci *ZookeeperConnectionInfo) withDefaults() (changed bool) {
	if ci.InternalConnectionString == "" {
		if ci.ExternalConnectionString != nil {
			changed = true
			ci.InternalConnectionString = *ci.ExternalConnectionString
		}
	}
	if ci.ChRoot == "" {
		changed = true
		ci.ChRoot = "/"
	} else if !strings.HasPrefix(ci.ChRoot, "/") {
		changed = true
		ci.ChRoot = "/" + ci.ChRoot
	}
	return changed
}

// ZookeeperACL defines acls to connect to a protected Zookeeper
type ZookeeperACL struct {
	// The name of the Kubernetes Secret that stores the username and password for the ACL.
	// This secret must be in the same namespace as the solrCloud or prometheusExporter is running in.
	SecretRef string `json:"secret"`

	// The name of the key in the given secret that contains the ACL username
	UsernameKey string `json:"usernameKey"`

	// The name of the key in the given secret that contains the ACL password
	PasswordKey string `json:"passwordKey"`
}
