package cn.stylefeng.workflow.instance.api.node;

import cn.stylefeng.workflow.api.entity.design.Node;
import cn.stylefeng.workflow.api.entity.instance.RuntimeNode;
import cn.stylefeng.workflow.api.enums.NodeStatusEnum;
import cn.stylefeng.workflow.api.enums.NodeTypeEnum;
import cn.stylefeng.workflow.api.pojo.InstanceContext;
import cn.stylefeng.workflow.instance.api.InstanceApi;
import cn.stylefeng.workflow.instance.api.RuntimeNodeApi;
import cn.stylefeng.workflow.instance.api.factory.RuntimeNodeFactory;
import cn.stylefeng.workflow.instance.api.pojo.NodeActionResult;
import jakarta.annotation.Resource;

import java.util.List;

public abstract class NodeAction {

    @Resource
    private RuntimeNodeApi runtimeNodeApi;

    @Resource
    private InstanceApi instanceApi;

    public RuntimeNode createRuntimeNode(Node nodeInfo, InstanceContext instanceContext) {
        Long instanceId = instanceContext.getRuntimeInstance().getInstanceId();
        return RuntimeNodeFactory.initRuntimeNode(nodeInfo, instanceId);
    }

    public RuntimeNode saveRuntimeNode(RuntimeNode runtimeNode) {
        return this.runtimeNodeApi.saveRuntimeNode(runtimeNode);
    }

    public RuntimeNode createAndSaveRuntimeNode(Node nodeInfo, InstanceContext instanceContext) {
        RuntimeNode runtimeNode = this.createRuntimeNode(nodeInfo, instanceContext);

        runtimeNode.setNodeStatus(NodeStatusEnum.FINISH.getStatus());

        return this.saveRuntimeNode(runtimeNode);
    }

    public RuntimeNode finishAndSaveRuntimeNode(RuntimeNode runtimeNode) {
        runtimeNode.setNodeStatus(NodeStatusEnum.FINISH.getStatus());
        return this.saveRuntimeNode(runtimeNode);
    }

    public List<Node> calcNextNodeList(Node nodeInfo, InstanceContext instanceContext) {
        return instanceApi.calcNextNodeList(nodeInfo, instanceContext);
    }

    public NodeActionResult directPassNode(Node nodeInfo, InstanceContext instanceContext) {

        RuntimeNode runtimeNode = this.createAndSaveRuntimeNode(nodeInfo, instanceContext);

        List<Node> nextNodeList = this.calcNextNodeList(nodeInfo, instanceContext);

        return new NodeActionResult(runtimeNode, nextNodeList, instanceContext.getInstanceVariable());
    }

    public void updateRuntimeNodeStatus(RuntimeNode runtimeNode) {
        this.runtimeNodeApi.updateRuntimeNode(runtimeNode);
    }

    public void saveOrUpdateRuntimeNode(RuntimeNode runtimeNode) {
        this.runtimeNodeApi.saveOrUpdateRuntimeNode(runtimeNode);
    }

    public abstract NodeTypeEnum getNodeType();

    public abstract NodeActionResult doAction(Node nodeInfo, InstanceContext instanceContext);

}
