// Now mutate funcs overwrite all fields of current objs
// It's not reasonable because some fields are omitted as default and set at server side
// TODO: optimize mutatefuncs
package mutatefuncs

import (
	admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

func MutateCRD(current, expected *apiextensionsv1.CustomResourceDefinition) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels

	current.Spec = expected.Spec

	return nil
}

func MutateDeployment(current, expected *appsv1.Deployment) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels
	current.Spec = expected.Spec

	return nil
}

func MutateService(current, expected *corev1.Service) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels

	current.Spec = expected.Spec

	return nil
}

func MutateServiceAccount(current, expected *corev1.ServiceAccount) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels

	if len(expected.Secrets) != 0 {
		current.Secrets = expected.Secrets
	}

	current.ImagePullSecrets = expected.ImagePullSecrets
	current.AutomountServiceAccountToken = expected.AutomountServiceAccountToken

	return nil
}

func MutateClusterRole(current, expected *rbacv1.ClusterRole) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels

	current.Rules = expected.Rules
	current.AggregationRule = expected.AggregationRule

	return nil
}

func MutateClusterRoleBinding(current, expected *rbacv1.ClusterRoleBinding) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels

	current.RoleRef = expected.RoleRef
	current.Subjects = expected.Subjects

	return nil
}

func MutateValidatingAdmissionPolicy(current, expected *admissionregistrationv1.ValidatingAdmissionPolicy) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels
	current.Spec = expected.Spec

	return nil
}

func MutateValidatingAdmissionPolicyBinding(current, expected *admissionregistrationv1.ValidatingAdmissionPolicyBinding) error {
	current.Annotations = expected.Annotations
	current.Labels = expected.Labels
	current.Spec = expected.Spec

	return nil
}

func UpsertServicePort(target *corev1.Service, port corev1.ServicePort) {
	for i := range target.Spec.Ports {
		p := &target.Spec.Ports[i]
		if p.Port != port.Port {
			continue
		}

		p.Name = port.Name
		p.Protocol = port.Protocol
		p.TargetPort = port.TargetPort
		// We don't use NodePort for now, so we don't need to update it.
		// p.NodePort = port.NodePort
		return
	}
	target.Spec.Ports = append(target.Spec.Ports, port)
}
