package config

import (
	"io/ioutil"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/yaml"
)

// TODO(tangent): Make multi-region work
type ImageConfig struct {
	Repo string `json:"repo"`
	Name string `json:"name"`
	Tag  string `json:"tag"`
	Ref  string `json:"ref"`
}

type RootConfig struct {
	ControllerConfig `json:",inline"`

	Predicate metav1.LabelSelector `json:"predicate"`
}

type ControllerConfig struct {
	Network NetworkConfig `json:"network"`
}

type NetworkConfig struct {
	CertManager CertManagerConfig `json:"certmanager"`
	CSI         CSIConfig         `json:"csi"`
	Operator    OperatorConfig    `json:"operator"`
	Proxy       ProxyConfig       `json:"proxy"`
	PCAIssuer   PCAIssuerConfig   `json:"pcaIssuer"`
}

type CertManagerConfig struct {
	HelmConfig `json:",inline"`

	CAInjectorImage ImageConfig `json:"cainjectorImage"`
	WebhookImage    ImageConfig `json:"webhookImage"`
	ControllerImage ImageConfig `json:"controllerImage"`
}

type CSIConfig struct {
	HelmConfig `json:",inline"`

	Driver              ImageConfig `json:"driver"`
	Provisioner         ImageConfig `json:"provisioner"`
	Attacher            ImageConfig `json:"attacher"`
	LivenessProbe       ImageConfig `json:"livenessProbe"`
	Resizer             ImageConfig `json:"resizer"`
	NodeDriverRegistrar ImageConfig `json:"nodeDriverRegistrar"`
}

type OperatorConfig struct {
	HelmConfig `json:",inline"`

	Operator            ImageConfig `json:"operator"`
	TidbBackupManager   ImageConfig `json:"tidbBackupManager"`
	AdvancedStatefulset ImageConfig `json:"advancedStatefulset"`
	KubeScheduler       ImageConfig `json:"kubeScheduler"`
}

type ProxyConfig struct {
	HelmConfig `json:",inline"`
	ProxyImage ImageConfig `json:"proxyImage"`
	GottyImage ImageConfig `json:"gottyImage"`
}

type PCAIssuerConfig struct {
	HelmConfig `json:",inline"`
	Image      ImageConfig `json:"image"`
}

// TODO(tangent): Validate CRD file exists
type HelmConfig struct {
	ChartPath string   `json:"chartPath"`
	CRDPaths  []string `json:"crdPaths"`
}

func LoadRootConfig(path string) (RootConfig, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return RootConfig{}, err
	}
	var config RootConfig
	err = yaml.Unmarshal(data, &config)
	if err != nil {
		return RootConfig{}, err
	}
	return config, nil
}
