package controller

import (
	batchv1 "k8s.io/api/batch/v1"
	batchv1beta1 "k8s.io/api/batch/v1beta1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (c *Controller) GetJobSpec(image string, labelMap map[string]string, command []string, env []corev1.EnvVar, volumeMount []corev1.VolumeMount,
	volume []corev1.Volume, serviceAccount string) *batchv1.JobSpec {
	return &batchv1.JobSpec{
		Template: corev1.PodTemplateSpec{
			ObjectMeta: metav1.ObjectMeta{
				Labels: labelMap,
			},
			Spec: corev1.PodSpec{
				RestartPolicy:      "OnFailure",
				ServiceAccountName: serviceAccount,
				Containers: []corev1.Container{
					{
						Name:            "meta-backup",
						Image:           image,
						ImagePullPolicy: "Always",
						Command:         command,
						VolumeMounts:    volumeMount,
						Env:             env,
					},
				},
				Volumes: volume,
			},
		},
	}
}

func (c *Controller) CreateJob(name string, namespace string, labelMap map[string]string, jobSpec batchv1.JobSpec) (*batchv1.Job, error) {

	// make sure namespace exist
	err := c.CreateNamespace(namespace)
	if err != nil {
		return nil, err
	}

	job := &batchv1.Job{
		ObjectMeta: metav1.ObjectMeta{
			Name:      name,
			Namespace: namespace,
			Labels:    labelMap,
		},
		Spec: jobSpec,
	}

	job, err = c.kubeCli.BatchV1().Jobs(namespace).Create(job)
	if err != nil && !errors.IsAlreadyExists(err) {
		return nil, err
	}
	return job, nil
}

func (c *Controller) GetJob(name, namespace string) (*batchv1.Job, error) {
	return c.kubeCli.BatchV1().Jobs(namespace).Get(name, metav1.GetOptions{})
}

func (c *Controller) ListJobs(namespace string, opts metav1.ListOptions) (*batchv1.JobList, error) {
	return c.kubeCli.BatchV1().Jobs(namespace).List(opts)
}

func (c *Controller) DeleteJob(name, namespace string) error {
	_, err := c.GetJob(name, namespace)
	if err != nil {
		if errors.IsNotFound(err) {
			return nil
		}
		return err
	}

	propagationPolicy := metav1.DeletePropagationForeground
	err = c.kubeCli.BatchV1().Jobs(namespace).Delete(name, &metav1.DeleteOptions{PropagationPolicy: &propagationPolicy})
	return err
}

func (c *Controller) CreateCronJob(namespace string, cronJob *batchv1beta1.CronJob) (*batchv1beta1.CronJob, error) {
	// make sure namespace exist
	err := c.CreateNamespace(namespace)
	if err != nil {
		return nil, err
	}

	cronJob, err = c.kubeCli.BatchV1beta1().CronJobs(namespace).Create(cronJob)
	if err != nil && !errors.IsAlreadyExists(err) {
		return nil, err
	}
	return cronJob, nil
}

func (c *Controller) GetCronJob(name, namespace string) (*batchv1beta1.CronJob, error) {
	return c.kubeCli.BatchV1beta1().CronJobs(namespace).Get(name, metav1.GetOptions{})
}

func (c *Controller) DeleteCronJob(name, namespace string) error {
	_, err := c.GetCronJob(name, namespace)
	if err != nil {
		if errors.IsNotFound(err) {
			return nil
		}
		return err
	}

	err = c.kubeCli.BatchV1beta1().CronJobs(namespace).Delete(name, &metav1.DeleteOptions{})
	return err
}

func (c *Controller) UpdateCronJob(namespace string, cronjob *batchv1beta1.CronJob) (*batchv1beta1.CronJob, error) {
	return c.kubeCli.BatchV1beta1().CronJobs(namespace).Update(cronjob)
}
