package framework

import (
	"fmt"
)

// TODO: hot reload, need to stop and re-create related running things

type ScalerUniqName string

// TODO: yaml/json mapping
type ClusterScalerConfig struct {
	ScalerUniqName  ScalerUniqName
	TargetClusterId ClusterId
	ExecutorName    ScalingTaskExecutorName
	ScalerConfig    ConfigData
	ExecutorConfig  ConfigData
	InputConfig     ConfigData
	OutputConfig    ConfigData
}

func (this *ClusterScalerConfig) UniqName() string {
	var scalerConfigUniqStr string
	if this.ScalerConfig != nil {
		scalerConfigUniqStr = this.ScalerConfig.UniqStr()
	}
	return fmt.Sprintf("ScalerName:%s;ClusterId:%s;ExecutorName:%s;ScalerConfigUniqStr:%s",
		this.ScalerUniqName,
		this.TargetClusterId,
		this.ExecutorName,
		scalerConfigUniqStr)
}

type ClusterScalerConfigManager struct {
	eventReceiver   EventReceiver
	configs         map[string]ClusterScalerConfig
	configUniqNames []string
}

func NewClusterScalerConfigManager(eventReceiver EventReceiver) *ClusterScalerConfigManager {
	return &ClusterScalerConfigManager{
		eventReceiver: eventReceiver,
		configs:       make(map[string]ClusterScalerConfig),
	}
}

func (this *ClusterScalerConfigManager) Iterate(fun func(config *ClusterScalerConfig) (keepGoing bool)) {
	for _, uniqName := range this.configUniqNames {
		config := this.configs[uniqName]
		keepGoing := fun(&config)
		if !keepGoing {
			break
		}
	}
}

func (this *ClusterScalerConfigManager) Add(config *ClusterScalerConfig, allowReplace bool) bool {
	uniqName := config.UniqName()
	_, ok := this.configs[uniqName]
	if ok {
		if !allowReplace {
			return false
		}
	} else {
		this.configUniqNames = append(this.configUniqNames, uniqName)
	}
	this.configs[uniqName] = *config
	this.eventReceiver.OnEvent(
		EventClusterScalerConfigManagerAddItem,
		EventDataWithName("ClusterScalerConfigItem", CloneableString(uniqName)))
	return true
}

var ClusterScalerConfigMockItem0 = &ClusterScalerConfig{
	ScalerUniqName:  ScalerConfigMockItem0.UniqName,
	TargetClusterId: "MockClusterId0",
	ExecutorName:    ScalerInterfaceV1ExecutorSyncLoopIdStr,
	ScalerConfig:    nil,
	ExecutorConfig: &ScalerInterfaceV1ExecutorSyncLoopConfig{
		PauseSecs: 3,
	},
}

var ClusterScalerConfigMockItem1 = &ClusterScalerConfig{
	ScalerUniqName:  ScalerConfigMockItem1.UniqName,
	TargetClusterId: "MockClusterId1",
	ExecutorName:    ScalerInterfaceV1ExecutorSyncLoopIdStr,
	ScalerConfig: &ClusterScalerPhasedComponentScalerV1Config{
		ComponentName:         ComponentName(InstanceNameMock),
		ComponentScalerConfig: nil,
	},
	ExecutorConfig: &ScalerInterfaceV1ExecutorSyncLoopConfig{
		PauseSecs: 3,
	},
}

func (this *ClusterScalerConfigManager) LoadMockConfig() {
	// this.Add(ClusterScalerConfigMockItem0, true)
	this.Add(ClusterScalerConfigMockItem1, true)
}

func (this *ClusterScalerConfigManager) LoadFromFile() error {
	// TODO: impl
	return nil
}
