package cn.axzo.workflow.core.engine.listener;

import cn.axzo.workflow.core.common.context.TaskOperationContext;
import cn.axzo.workflow.core.listener.BpmnTaskEventListener;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 引擎用户任务事件监听, 用于 BPMN 文件中为节点设置指定类型监听
 *
 * @author wangli
 */
@Slf4j
@Component
public class EngineTaskEventListener implements TaskListener {

    @Resource
    ObjectProvider<List<BpmnTaskEventListener>> taskEventListeners;


    @Override
    public void notify(DelegateTask delegateTask) {
        log.info("Task Listener, Event: ALL , TaskId: {}, EventName: {}", delegateTask.getId(),
                delegateTask.getEventName());

        StopWatch stopWatch = new StopWatch("EngineTaskEventListener");
        stopWatch.start("All Task Event Execution Time");
        getOrderedListeners().forEach(i -> {
            if (Objects.isNull(delegateTask.getEventName())) {
                // FIXME 这里不知道为什么, 从 1.2.1 版本出现了NPE, 通过堆栈未找到根因. 有空再跟进
                return;
            }
            switch (delegateTask.getEventName()) {
                case EVENTNAME_ASSIGNMENT:
                    i.onAssigned(delegateTask);
                    break;
                case EVENTNAME_CREATE:
                    i.onCreated(delegateTask);
                    break;
                case EVENTNAME_COMPLETE:
                    // 审批通过
                    i.onCompleted(delegateTask);
                    break;
                case EVENTNAME_DELETE:
                    // 审批
                    i.onDeleted(delegateTask);
                    break;
                default:
            }
        });
        log.info("StopWatch '" + stopWatch.currentTaskName() + "': running time = " + stopWatch.getTotalTimeSeconds() + " s");
        stopWatch.stop();

    }

    /**
     * 获取排序后的监听器
     *
     * @return
     */
    private List<BpmnTaskEventListener> getOrderedListeners() {
        TaskOperationContext context = new TaskOperationContext();
        List<BpmnTaskEventListener> orderListeners = new ArrayList<>();
        taskEventListeners.ifAvailable(orderListeners::addAll);
        orderListeners.forEach(i -> i.setContext(context));
        return orderListeners;
    }

}
