package cn.axzo.workflow.server.controller.listener.activity;

import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventProducer;
import cn.axzo.workflow.common.enums.ProcessActivityEventEnum;
import cn.axzo.workflow.common.model.response.mq.ProcessActivityDTO;
import cn.axzo.workflow.core.listener.BpmnActivityEventListener;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEvent;
import org.flowable.engine.delegate.event.FlowableActivityCancelledEvent;
import org.flowable.engine.delegate.event.FlowableActivityEvent;
import org.flowable.engine.delegate.event.FlowableMultiInstanceActivityCancelledEvent;
import org.flowable.engine.delegate.event.FlowableMultiInstanceActivityCompletedEvent;
import org.flowable.engine.delegate.event.FlowableMultiInstanceActivityEvent;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import static cn.axzo.workflow.common.enums.ProcessActivityEventEnum.PROCESS_ACTIVITY_CANCELLED;
import static cn.axzo.workflow.common.enums.ProcessActivityEventEnum.PROCESS_ACTIVITY_COMPLETED;
import static cn.axzo.workflow.common.enums.ProcessActivityEventEnum.PROCESS_ACTIVITY_STARTED;

/**
 * 自定义实现的活动节点监听器, 实现了 Ordered 接口
 * <p>
 * 注意:Order 值越小,优先级越高
 *
 * @author wangli
 * @since 2023/7/24 17:33
 */
@Slf4j
@Component
public class RocketMqBpmActivityEventListener implements BpmnActivityEventListener, Ordered {

    @Resource
    private EventProducer<?> eventProducer;

    @Override
    public void onStarted(FlowableEngineEvent event) {
        if (log.isDebugEnabled()) {
            log.debug("activity started event");
        }
        ProcessActivityDTO dto = new ProcessActivityDTO();
        dto.setType(PROCESS_ACTIVITY_STARTED);
        dto.setProcessInstanceId(event.getProcessInstanceId());
        dto.setProcessDefinitionId(event.getProcessDefinitionId());
        // 这个 ID 等于 ExecutionId
        dto.setTriggerId(event.getSubScopeId());
        if (event instanceof FlowableActivityEvent) {
            FlowableActivityEvent flowableEvent = (FlowableActivityEvent) event;
            dto.setActivityId(flowableEvent.getActivityId());
            dto.setActivityName(flowableEvent.getActivityName());

        } else if (event instanceof FlowableMultiInstanceActivityEvent) {
            FlowableMultiInstanceActivityEvent flowableEvent = (FlowableMultiInstanceActivityEvent) event;
            dto.setActivityId(flowableEvent.getActivityId());
            dto.setActivityName(flowableEvent.getActivityName());
        }
        log.info("RocketMqBpmActivityEventListener#onStarted MQ.Data: {}", JSON.toJSONString(dto));
        sendMessageQueue(dto, PROCESS_ACTIVITY_STARTED);
    }

    @Override
    public void onCompleted(FlowableEngineEvent event) {
        if (log.isDebugEnabled()) {
            log.debug("activity completed event");
        }
        ProcessActivityDTO dto = new ProcessActivityDTO();
        dto.setType(PROCESS_ACTIVITY_COMPLETED);
        dto.setProcessInstanceId(event.getProcessInstanceId());
        dto.setProcessDefinitionId(event.getProcessDefinitionId());
        // 这个 ID 等于 ExecutionId
        dto.setTriggerId(event.getSubScopeId());
        if (event instanceof FlowableActivityEvent) {
            FlowableActivityEvent flowableEvent = (FlowableActivityEvent) event;
            dto.setActivityId(flowableEvent.getActivityId());
            dto.setActivityName(flowableEvent.getActivityName());
        } else if (event instanceof FlowableMultiInstanceActivityCompletedEvent) {
            FlowableMultiInstanceActivityCompletedEvent flowableEvent =
                    (FlowableMultiInstanceActivityCompletedEvent) event;
            dto.setActivityId(flowableEvent.getActivityId());
            dto.setActivityName(flowableEvent.getActivityName());
        }
        log.info("RocketMqBpmActivityEventListener#onCompleted MQ.Data: {}", JSON.toJSONString(dto));
        sendMessageQueue(dto, PROCESS_ACTIVITY_COMPLETED);
    }

    @Override
    public void onCancelled(FlowableEngineEvent event) {
        if (log.isDebugEnabled()) {
            log.debug("activity cancelled event");
        }
        ProcessActivityDTO dto = new ProcessActivityDTO();
        dto.setType(PROCESS_ACTIVITY_CANCELLED);
        dto.setProcessInstanceId(event.getProcessInstanceId());
        dto.setProcessDefinitionId(event.getProcessDefinitionId());
        // 这个 ID 等于 ExecutionId
        dto.setTriggerId(event.getSubScopeId());
        if (event instanceof FlowableActivityCancelledEvent) {
            FlowableActivityCancelledEvent flowableEvent = (FlowableActivityCancelledEvent) event;
            dto.setActivityId(flowableEvent.getActivityId());
            dto.setActivityName(flowableEvent.getActivityName());
        } else if (event instanceof FlowableMultiInstanceActivityCancelledEvent) {
            FlowableMultiInstanceActivityCancelledEvent flowableEvent =
                    (FlowableMultiInstanceActivityCancelledEvent) event;
            dto.setActivityId(flowableEvent.getActivityId());
            dto.setActivityName(flowableEvent.getActivityName());
        }

        log.info("RocketMqBpmActivityEventListener#onCancelled MQ.Data: {}", JSON.toJSONString(dto));
        sendMessageQueue(dto, PROCESS_ACTIVITY_CANCELLED);
    }


    private void sendMessageQueue(ProcessActivityDTO dto, ProcessActivityEventEnum eventEnum) {
        eventProducer.send(Event.builder()
                .shardingKey(dto.getActivityId())
                .eventCode(eventEnum.getEventCode())
                .targetId(dto.getActivityId())
                .targetType(eventEnum.getTag())
                .data(dto)
                .build());
    }

    @Override
    public int getOrder() {
        return Integer.MIN_VALUE;
    }
}
