package cn.axzo.workflow.starter.mq.broadcast.consumer;

import cn.axzo.framework.rocketmq.Event;
import cn.axzo.framework.rocketmq.EventConsumer;
import cn.axzo.workflow.common.enums.ProcessInstanceEventEnum;
import cn.axzo.workflow.common.model.response.mq.ProcessInstanceDTO;
import cn.axzo.workflow.starter.handler.ProcessInstanceEventHandler;
import cn.axzo.workflow.starter.handler.execute.ListenerExecutor;
import cn.axzo.workflow.starter.handler.filter.ProcessInstanceEventFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;

import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * @author wangli
 * @since 2024/5/21 15:51
 */
public class InnerInstanceEventListener extends AbstractWorkflowListener<ProcessInstanceEventHandler, ProcessInstanceEventFilter, ProcessInstanceDTO> {
    private final Logger log = LoggerFactory.getLogger(InnerInstanceEventListener.class);

    public final static Supplier<List<Event.EventCode>> SUPPORTED_EVENT_CODES_SUPPLIER = () ->
            Arrays.stream(ProcessInstanceEventEnum.values()).map(ProcessInstanceEventEnum::getEventCode)
                    .collect(Collectors.toList());

    public InnerInstanceEventListener(ListenerExecutor listenerExecutor,
                                      ObjectProvider<List<ProcessInstanceEventHandler>> handlerProvider,
                                      ObjectProvider<List<ProcessInstanceEventFilter>> filterProvider) {
        super(listenerExecutor, handlerProvider, filterProvider);
    }

    @Override
    protected ProcessInstanceDTO convert(Event event) {
        return event.normalizedData(ProcessInstanceDTO.class);
    }

    @Override
    public void onEvent(ProcessInstanceDTO instanceDTO, EventConsumer.Context context) {
        ProcessInstanceEventEnum type = instanceDTO.getType();
        for (ProcessInstanceEventHandler instanceListener : businessListeners) {
            Consumer<ProcessInstanceDTO> consumer = null;
            switch (type) {
                case PROCESS_INSTANCE_CREATED:
                    consumer = instanceListener::onCreated;
                    break;
                case PROCESS_INSTANCE_STARTED:
                    consumer = instanceListener::onStarted;
                    break;
                case PROCESS_INSTANCE_CANCELLED:
                    consumer = instanceListener::onCancelled;
                    break;
                case PROCESS_INSTANCE_ABORTED:
                    consumer = instanceListener::onAborted;
                    break;
                case PROCESS_INSTANCE_COMPLETED:
                    consumer = instanceListener::onCompleted;
                    break;
                case PROCESS_INSTANCE_REJECTED:
                    consumer = instanceListener::onRejected;
                    break;
                default:
                    log.warn("unknown process activity event type: {}", type);
            }
            getListenerExecutor().execute(consumer, instanceDTO);
        }
    }

    @Override
    protected List<Event.EventCode> getSupportEventCodes() {
        return SUPPORTED_EVENT_CODES_SUPPLIER.get();
    }

}
