/*
 * This file is part of the KubeVirt project
 *
 * Licensed 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.
 *
 * Copyright The KubeVirt Authors.
 *
 */

package annotations

import (
	"fmt"
	"strconv"

	v1 "kubevirt.io/api/core/v1"

	"kubevirt.io/kubevirt/pkg/storage/velero"
)

const computeContainerName = "compute"

type kubeVirtCRProvider interface {
	GetConfigFromKubeVirtCR() *v1.KubeVirt
}

type Generator struct {
	clusterConfig kubeVirtCRProvider
}

func NewGenerator(clusterConfig kubeVirtCRProvider) Generator {
	return Generator{clusterConfig: clusterConfig}
}

func (g Generator) ManagedAnnotationKeys() []string {
	return []string{
		velero.PreBackupHookContainerAnnotation,
		velero.PreBackupHookCommandAnnotation,
		velero.PreBackupHookTimeoutAnnotation,
		velero.PostBackupHookContainerAnnotation,
		velero.PostBackupHookCommandAnnotation,
	}
}

func (g Generator) Generate(vmi *v1.VirtualMachineInstance) (map[string]string, error) {
	// Check VMI annotation first, fallback to kubevirt CR if not set
	skipValue, hasSkipValue := vmi.Annotations[velero.SkipHooksAnnotation]
	if !hasSkipValue && g.clusterConfig != nil {
		kubeVirtCR := g.clusterConfig.GetConfigFromKubeVirtCR()
		if kubeVirtCR != nil {
			skipValue = kubeVirtCR.Annotations[velero.SkipHooksAnnotation]
		}
	}

	annotations := map[string]string{}

	skip, _ := strconv.ParseBool(skipValue)
	if !skip {
		annotations[velero.PreBackupHookContainerAnnotation] = computeContainerName
		annotations[velero.PreBackupHookCommandAnnotation] = fmt.Sprintf(
			"[\"/usr/bin/virt-freezer\", \"--freeze\", \"--name\", %q, \"--namespace\", %q]",
			vmi.Name,
			vmi.Namespace,
		)
		annotations[velero.PreBackupHookTimeoutAnnotation] = "60s"
		annotations[velero.PostBackupHookContainerAnnotation] = computeContainerName
		annotations[velero.PostBackupHookCommandAnnotation] = fmt.Sprintf(
			"[\"/usr/bin/virt-freezer\", \"--unfreeze\", \"--name\", %q, \"--namespace\", %q]",
			vmi.Name,
			vmi.Namespace,
		)
	}

	return annotations, nil
}
