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.ProcessActivityEventEnum;
import cn.axzo.workflow.common.model.response.mq.ProcessActivityDTO;
import cn.axzo.workflow.starter.handler.ProcessActivityEventHandler;
import cn.axzo.workflow.starter.handler.execute.ListenerExecutor;
import cn.axzo.workflow.starter.handler.filter.ProcessActivityEventFilter;
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 InnerActivityEventListener extends AbstractWorkflowListener<ProcessActivityEventHandler, ProcessActivityEventFilter, ProcessActivityDTO> {
    private final Logger log = LoggerFactory.getLogger(InnerActivityEventListener.class);

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

    public InnerActivityEventListener(ListenerExecutor executor,
                                      ObjectProvider<List<ProcessActivityEventHandler>> provider,
                                      ObjectProvider<List<ProcessActivityEventFilter>> filterProvider) {
        super(executor, provider, filterProvider);
    }

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

    @Override
    public void onEvent(ProcessActivityDTO activityDTO, EventConsumer.Context context) {
        ProcessActivityEventEnum type = activityDTO.getType();
        for (ProcessActivityEventHandler activityListener : businessListeners) {
            Consumer<ProcessActivityDTO> consumer = null;
            switch (type) {
                case PROCESS_ACTIVITY_START:
                    consumer = activityListener::onStart;
                    break;
                case PROCESS_ACTIVITY_WAIT_ASSIGNEE:
                    consumer = activityListener::onWaitAssignee;
                    break;
                case PROCESS_ACTIVITY_TAKE:
                    consumer = activityListener::onTake;
                    break;
                case PROCESS_ACTIVITY_END:
                    consumer = activityListener::onEnd;
                    break;
                default:
                    log.warn("unknown process activity event type: {}", type);
            }
            getListenerExecutor().execute(consumer, activityDTO);
        }
    }

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

}
