package extended

import (
	"fmt"

	o "github.com/onsi/gomega"

	exutil "github.com/openshift/machine-config-operator/test/extended-priv/util"
	logger "github.com/openshift/machine-config-operator/test/extended-priv/util/logext"
)

// KubeletConfig struct is used to handle KubeletConfig resources in OCP
type KubeletConfig struct {
	Resource
	template string
}

// KubeletConfigList handles list of nodes
type KubeletConfigList struct {
	ResourceList
}

// NewKubeletConfig create a NewKubeletConfig struct
func NewKubeletConfig(oc *exutil.CLI, name, template string) *KubeletConfig {
	return &KubeletConfig{Resource: *NewResource(oc, "KubeletConfig", name), template: template}
}

// NewKubeletConfigList create a NewKubeletConfigList struct
func NewKubeletConfigList(oc *exutil.CLI) *KubeletConfigList {
	return &KubeletConfigList{*NewResourceList(oc, "KubeletConfig")}
}

func (kc *KubeletConfig) create(parameters ...string) {
	allParams := []string{"--ignore-unknown-parameters=true", "-f", kc.template,
		"-p", "NAME=" + kc.name}
	allParams = append(allParams, parameters...)
	exutil.CreateClusterResourceFromTemplate(kc.oc, allParams...)
}

// waitUntilSuccess polls until the KubeletConfig reports a Accepted=True condition.
func (kc KubeletConfig) waitUntilSuccess(timeout string) {
	logger.Infof("wait for %s to report success", kc.name)
	o.EventuallyWithOffset(1, &kc, timeout, "2s").Should(o.SatisfyAll(
		HaveConditionField("Accepted", "status", "True"),
		HaveConditionField("Accepted", "message", "Success"),
	), "KubeletConfig '%s' should report Accepted=True in status.conditions, but the current status is not success", kc.GetName())
}

// waitUntilFailure polls until the KubeletConfig reports a Accepted=False condition with the expected message.
func (kc KubeletConfig) waitUntilFailure(expectedMsg, timeout string) {
	logger.Infof("wait for %s to report failure", kc.name)
	o.EventuallyWithOffset(1, &kc, timeout, "2s").Should(o.SatisfyAll(
		HaveConditionField("Accepted", "status", "False"),
		HaveConditionField("Accepted", "message", o.ContainSubstring(expectedMsg)),
	), "KubeletConfig '%s' should report Accepted=False in status.conditions and report failure message %s. But it doesn't.", kc.GetName(), expectedMsg)
}

// GetGeneratedMCName returns the name of the MC that was generated by this KubeletConfig resource
func (kc KubeletConfig) GetGeneratedMCName() (string, error) {
	mcName, err := kc.Get(`{.metadata.finalizers[0]}`)
	if err != nil {
		return "", err
	}
	if mcName == "" {
		return "", fmt.Errorf("it was not possible to get the finalizer from %s %s: %s", kc.GetKind(), kc.GetName(), kc.PrettyString())
	}
	return mcName, nil
}

// GetGeneratedMCNameOrFail returns the name of the MC that was generated by this KubeletConfig resource and fails the test case if it cannot be done
func (kc KubeletConfig) GetGeneratedMCNameOrFail() string {
	mcName, err := kc.GetGeneratedMCName()
	o.Expect(err).NotTo(o.HaveOccurred(), "Error getting the generated MC for %s %s", kc.GetKind(), kc.GetName())
	return mcName
}
