package v1

import "strings"

// +kubebuilder:object:root=false
type ComponentSpec struct {
	BaseImage *string
	Tag       *string
	Config    *TomlConfig
}

// +kubebuilder:object:root=false
type PDClusterConfig struct {
	*TomlConfig
}

// +kubebuilder:object:root=false
type PDInstanceConfig struct {
	*TomlConfig
}

func (cc *ClusterConfig) IsDryrun() bool {
	return cc.GetUpdatePolicy() == UpdatePolicyDryrun
}

// GetUpdatePolicy get the update policy
func (cc *ClusterConfig) GetUpdatePolicy() UpdatePolicy {
	if len(cc.Spec.UpdatePolicy) < 1 {
		// default value for backward compatibility
		return UpdatePolicyDryrun
	}
	return cc.Spec.UpdatePolicy
}

func GetPDClusterConfig(conf *TomlConfig) *PDClusterConfig {
	clone := conf.DeepCopy()
	for k := range clone.MP {
		if !IsPDClusterConfig(k) {
			delete(clone.MP, k)
		}
	}
	// special treatment for replication.location-labels
	if rep, ok := clone.MP["replication"]; ok {
		if repMap, ok := rep.(map[string]interface{}); ok {
			if ls, ok := repMap["location-labels"]; ok {
				if lList, ok := ls.([]interface{}); ok {
					sb := strings.Builder{}
					for i, s := range lList {
						if i != 0 {
							sb.WriteString(",")
						}
						sb.WriteString(s.(string))
					}
					repMap["location-labels"] = sb.String()
				}
			}
		}
	}
	return &PDClusterConfig{clone}
}

// GetPDClusterConfig returns the PD instance-level configuration stored in per PD node
func GetPDInstanceConfig(conf *TomlConfig) *PDInstanceConfig {
	clone := conf.DeepCopy()
	for k := range clone.MP {
		if IsPDClusterConfig(k) {
			delete(clone.MP, k)
		}
	}
	return &PDInstanceConfig{clone}
}

func ExtractPDClusterConfig(m map[string]interface{}) *PDClusterConfig {
	if m == nil {
		return &PDClusterConfig{NewTomlConfig(map[string]interface{}{})}
	}
	out := map[string]interface{}{}
	for k := range m {
		if IsPDClusterConfig(k) {
			out[k] = m[k]
		}
	}
	return &PDClusterConfig{NewTomlConfig(out)}
}

func IsPDClusterConfig(k string) bool {
	return k == "schedule" || k == "replication"
}
