package plugins

import (
	"os/exec"

	"github.com/smartcontractkit/chainlink-common/pkg/loop"
)

// RegistrarConfig generates contains static configuration
type RegistrarConfig interface {
	RegisterLOOP(config CmdConfig) (func() *exec.Cmd, loop.GRPCOpts, error)
	UnregisterLOOP(ID string)
}

type registarConfig struct {
	grpcOpts           loop.GRPCOpts
	loopRegistrationFn func(loopId string) (*RegisteredLoop, error)
	loopUnregisterFn   func(loopId string)
}

// NewRegistrarConfig creates a RegistarConfig
// loopRegistrationFn must act as a global registry function of LOOPs and must be idempotent.
// The [func() *exec.Cmd] for a LOOP should be generated by calling [RegistrarConfig.RegisterLOOP]
func NewRegistrarConfig(grpcOpts loop.GRPCOpts, loopRegistrationFn func(loopId string) (*RegisteredLoop, error), loopUnregisterFn func(loopId string)) RegistrarConfig {
	return &registarConfig{
		grpcOpts:           grpcOpts,
		loopRegistrationFn: loopRegistrationFn,
		loopUnregisterFn:   loopUnregisterFn,
	}
}

// RegisterLOOP calls the configured loopRegistrationFn. The loopRegistrationFn must act as a global registry for LOOPs and must be idempotent.
func (pc *registarConfig) RegisterLOOP(cfg CmdConfig) (func() *exec.Cmd, loop.GRPCOpts, error) {
	cmdFn, err := NewCmdFactory(pc.loopRegistrationFn, cfg)
	if err != nil {
		return nil, loop.GRPCOpts{}, err
	}
	return cmdFn, pc.grpcOpts, nil
}

func (pc *registarConfig) UnregisterLOOP(ID string) {
	pc.loopUnregisterFn(ID)
}
