package framework

import (
	"fmt"
)

type PhasedComponentScalerCreator func(
	eventReceiver EventReceiver,
	clusterId ClusterId,
	componentName ComponentName,
	config ConfigData,
	pInputInterface, pOutputInterface any) (pScaler any, err error)

type PhasedComponentScalerManager struct {
	eventReceiver EventReceiver
	creators      map[PhasedComponentScalerType]PhasedComponentScalerCreator
}

func NewPhasedComponentScalerManager(eventReceiver EventReceiver) *PhasedComponentScalerManager {
	return &PhasedComponentScalerManager{
		eventReceiver: eventReceiver,
		creators:      make(map[PhasedComponentScalerType]PhasedComponentScalerCreator),
	}
}

func (this *PhasedComponentScalerManager) Register(scalerType PhasedComponentScalerType, creator PhasedComponentScalerCreator) error {
	_, ok := this.creators[scalerType]
	if ok {
		this.eventReceiver.OnEvent(
			EventPhasedComponentScalerManagerRegisterCreatorDuplicated,
			EventDataWithName("PhasedComponentScalerType", CloneableString(scalerType)))
		return fmt.Errorf("[PhasedComponentScalerManager.Register] creator `%s` already exists", scalerType)
	}
	this.creators[scalerType] = creator
	this.eventReceiver.OnEvent(
		EventPhasedComponentScalerManagerRegisterCreatorOk,
		EventDataWithName("PhasedComponentScalerType", CloneableString(scalerType)))
	return nil
}

func (this *PhasedComponentScalerManager) NewPhasedComponentScaler(
	scalerType PhasedComponentScalerType,
	clusterId ClusterId,
	componentName ComponentName,
	config ConfigData,
	pInputInterface, pOutputInterface any) (any, error) {

	creator, ok := this.creators[scalerType]
	if !ok {
		this.eventReceiver.OnEvent(
			EventPhasedComponentScalerManagerCreatorNotFound,
			EventDataWithName("PhasedComponentScalerType", CloneableString(scalerType)))
		return nil, fmt.Errorf("[PhasedComponentScalerManager.NewPhasedComponentScaler] scaler type `%s` does not exist", scalerType)
	}
	scaler, err := creator(this.eventReceiver, clusterId, componentName, config, pInputInterface, pOutputInterface)
	if err != nil {
		return nil, err
	}
	this.eventReceiver.OnEvent(
		EventPhasedComponentScalerManagerCreatedScaler,
		EventDataWithName("PhasedComponentScalerType", CloneableString(scalerType)))
	return scaler, nil
}

func NewDefaultPhasedComponentScalerManager(eventReceiver EventReceiver) (*PhasedComponentScalerManager, error) {
	manager := NewPhasedComponentScalerManager(eventReceiver)

	err := manager.Register(
		PhasedComponentScalerMockEmptyIdStr,
		func(eventReceiver EventReceiver, clusterId ClusterId, componentName ComponentName, _ ConfigData, _, _ any) (any, error) {
			return NewPhasedComponentScalerMockEmpty(eventReceiver, clusterId, componentName), nil
		},
	)
	if err != nil {
		return nil, err
	}

	return manager, nil
}
