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

import cn.axzo.workflow.core.listener.BpmnAsyncJobEventListener;
import com.google.common.collect.ImmutableSet;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
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.Set;

/**
 * 引擎异步任务事件监听器
 *
 * @author wangli
 * @since 2024/4/29 16:48
 */
@Slf4j
@Component
public class EngineAsyncJobEventListener extends AbstractFlowableEngineEventListener {

    @Resource
    ObjectProvider<List<BpmnAsyncJobEventListener>> asyncJobListeners;

    public static final Set<FlowableEngineEventType> ASYNC_JOB_EVENTS =
            ImmutableSet.<FlowableEngineEventType>builder()
                    .add(FlowableEngineEventType.JOB_CANCELED)
                    .add(FlowableEngineEventType.JOB_EXECUTION_SUCCESS)
                    .add(FlowableEngineEventType.JOB_EXECUTION_FAILURE)
                    .add(FlowableEngineEventType.JOB_RETRIES_DECREMENTED)
                    .add(FlowableEngineEventType.JOB_REJECTED)
                    .add(FlowableEngineEventType.JOB_RESCHEDULED)
                    .add(FlowableEngineEventType.JOB_MOVED_TO_DEADLETTER)
                    .build();

    public EngineAsyncJobEventListener() {
        super(ASYNC_JOB_EVENTS);
    }

    @Override
    public void onEvent(FlowableEvent flowableEvent) {
        StopWatch stopWatch = new StopWatch("EngineAsyncJobEventListener");
        stopWatch.start("async-job-event-listener");
        if (ASYNC_JOB_EVENTS.contains(flowableEvent.getType())) {
            getOrderedListeners().forEach(i -> {
                if (i.support((FlowableEngineEventType) flowableEvent.getType())) {
                    i.notify(flowableEvent);
                }
            });
        }
        stopWatch.stop();
    }

    private List<BpmnAsyncJobEventListener> getOrderedListeners() {
        List<BpmnAsyncJobEventListener> orderListeners = new ArrayList<>();
        asyncJobListeners.ifAvailable(orderListeners::addAll);
        return orderListeners;
    }
}
