package taskruns

import (
	"github.com/pingcap/test-infra/common/model"
	"github.com/pingcap/test-infra/common/model/tcms/general"
	reqM "github.com/pingcap/test-infra/common/model/tcms/request"
)

type SvcTask struct {
	general.GeneralHeader
	MetaData       general.GeneralMetaData `json:"metadata"`
	Name           string                  `json:"name"`
	Description    string                  `json:"description"`
	Inputs         []TaskInputDecl         `json:"inputs"`
	Outputs        []TaskOutputDecl        `json:"outputs"`
	Implementation SvcTaskImplementation   `json:"implementation"`
}

type TaskType string

const (
	TaskTypeUnknown TaskType = ""
	TaskTypePlan    TaskType = "Plan"
	TaskTypeMock    TaskType = "Mock"
)

type SvcTaskImplementation struct {
	Plan *PlanImplementation `json:"plan,omitempty"`
	Mock *MockImplementation `json:"mock,omitempty"`
}

func (t SvcTaskImplementation) GetType() TaskType {
	if t.Plan != nil {
		return TaskTypePlan
	} else if t.Mock != nil {
		return TaskTypeMock
	}
	return TaskTypeUnknown
}

type PlanImplementation struct {
	model.PlanRef
	Spec *reqM.PlanCreateRequest `json:"spec"`
}

type TaskInputDecl struct {
	Name        string `json:"name"`
	Type        string `json:"type,omitempty"`
	Description string `json:"description,omitempty"`
	Default     string `json:"default,omitempty"`
}

type TaskOutputDecl struct {
	Name        string `json:"name"`
	Type        string `json:"type,omitempty"`
	Description string `json:"description,omitempty"`
}

type MockImplementation struct {
	Outputs TaskRunOutputs `json:"outputs"`
}

type SvcTaskRun struct {
	general.GeneralHeader
	MetaData general.GeneralMetaData `json:"metadata"`
	Spec     SvcTaskRunSpec          `json:"spec"`
	Status   SvcTaskRunStatus        `json:"status"`
}

type TaskInputBind struct {
	Name  string `json:"name"`
	Value string `json:"value,omitempty"`
}

type TaskRunOutput struct {
	Name  string `json:"name"`
	Value string `json:"value,omitempty"`
}

type SvcTaskRunSpec struct {
	SvcTaskName string          `json:"svcTaskName"`
	Inputs      []TaskInputBind `json:"inputs,omitempty"`
}

type SvcTaskRunStatus struct {
	Implementation SvcTaskRunImplementation `json:"implementation"`
	Completed      bool                     `json:"completed"`
	Message        string                   `json:"message,omitempty"`
	Outputs        TaskRunOutputs           `json:"outputs,omitempty"`
}

type TaskRunOutputs []TaskRunOutput

func (t *TaskRunOutputs) SetValue(name string, value string) {
	found := false
	for i, output := range *t {
		if output.Name == name {
			(*t)[i].Value = value
			found = true
			break
		}
	}
	if !found {
		*t = append(*t, TaskRunOutput{Name: name, Value: value})
	}
}

type SvcTaskRunImplementation struct {
	Plan *PlanExecRef `json:"plan,omitempty"`
}

type PlanExecRef struct {
	ExecID model.ID `json:"execID"`
}

func (t SvcTaskRunImplementation) GetType() TaskType {
	if t.Plan != nil {
		return TaskTypePlan
	}
	return TaskTypeUnknown
}
