package executor

import (
	"fmt"

	"github.com/tidbcloud/cluster-service-ng/pkg/runtime/actions"
)

type ActionRender interface {
	Render(in string) (actions.Action, error)
}

type ActionRenderLibrary struct {
	renders map[string]ActionRender
}

func NewActionRenderLibrary() *ActionRenderLibrary {
	return &ActionRenderLibrary{make(map[string]ActionRender)}
}

func (arl *ActionRenderLibrary) Register(name string, render ActionRender) error {
	if _, ok := arl.renders[name]; ok {
		return fmt.Errorf("ActionRenderLibrary.Register: action render `%s` already existed", name)
	}
	arl.renders[name] = render
	return nil
}

func (arl *ActionRenderLibrary) SafeRegister(name string, render ActionRender) {
	err := arl.Register(name, render)
	if err != nil {
		panic(err)
	}
}

func (arl *ActionRenderLibrary) Render(
	name string,
	in string) (actions.Action, error) {

	render, ok := arl.renders[name]
	if !ok {
		return nil, fmt.Errorf("ActionRenderLibrary.Render: action render `%s` not found", name)
	}
	return render.Render(in)
}

type BuiltinFunctionActionRenderV1 struct {
}

func NewBuiltinFunctionActionRenderV1() *BuiltinFunctionActionRenderV1 {
	return nil
}

func (bfar *BuiltinFunctionActionRenderV1) Render(in string) (actions.Action, error) {
	// TODO: design the format in yaml, impl
	panic("")
}

type K8sActionRenderV1 struct {
}

func NewK8sActionRenderV1() *K8sActionRenderV1 {
	return nil
}

func (kar *K8sActionRenderV1) Render(in string) (actions.Action, error) {
	// TODO: design the format in yaml, impl
	panic("")
}

type CallAnotherActionRenderV1 struct {
}

func NewCallAnotherActionRenderV1() *CallAnotherActionRenderV1 {
	return nil
}

func (car *CallAnotherActionRenderV1) Render(in string) (actions.Action, error) {
	// TODO: design the format in yaml, impl
	panic("TODO: impl")
}

// the actions CRD is an action list/array, don't have dependency definition
const ExampleOfActionDefinitions = `
- name: "create-tikv-worker:v1"
  render:
    name: "k8s-action-render:v1"
    input:
      method: "set"
      template:
        name: "tikv-worker-deployment:v1"

- name: "create-tikv-worker:v1"
  render:
    name: "k8s-action-render:v1"
    input:
      method: "set"
      template:
        name: "tikv-worker-deployment:v1"
      finish-expectation:
        (define where to fetch the status and the expected value)
        k8s-endpoint: ...

- name: "foo-bar:v1"
  render:
    name: "builtin-function-action-render:v1"
    input:
      function: "foo-bar (<-FooBar)" (all functions are 'func(args Args)', the type of args depends on the function name)
...
`
