
package com.mortals.xhx.queue;

import com.mortals.xhx.queue.processing.AbstractConsumerService;
import com.mortals.xhx.queue.provider.TbCoreQueueFactory;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

@Service
@Slf4j
public class DefaultTbCoreConsumerService extends AbstractConsumerService<TbQueueMsg> implements TbCoreConsumerService {

    @Value("${queue.core.poll-interval}")
    private long pollDuration;//队列拉取时间间隔，单位毫秒
    @Value("${queue.core.pack-processing-timeout}")
    private long packProcessingTimeout;

    @Getter
    private LinkedBlockingQueue<TbQueueMsg> comsureQueue = new LinkedBlockingQueue<>();

    @Getter
    private TbQueueConsumer<TbQueueMsg> mainConsumer;
    @Getter
    private List<TbQueueConsumer<TbQueueMsg>> consumerList;

    /**
     * 根据配置文件动态加载kafka,rabbmitMq等工厂类
     * @param tbCoreQueueFactory
     */
    public DefaultTbCoreConsumerService(TbCoreQueueFactory tbCoreQueueFactory) {
        //通过工厂类创建通道
        this.mainConsumer = tbCoreQueueFactory.createMsgConsumer();

        //tbCoreQueueFactory.createListMsgConsumer()
    }

    @PostConstruct
    public void init() {
        log.info("初始化消费服务线程");
        super.init("core-consumer");
    }

    @PreDestroy
    public void destroy() {
        super.destroy();
    }


    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
    }

    @Override
    protected void launchMainConsumers() {
        log.info("启动消费线程！");
        consumersExecutor.submit(() -> {
            while (!stopped) {
                try {
                    List<TbQueueMsg> msgs = mainConsumer.poll(pollDuration);
                    if (msgs.isEmpty()) {
                        continue;
                    }
                    for (TbQueueMsg item : msgs) {
                        comsureQueue.offer(item);
                    }

                    mainConsumer.commit();
                } catch (Exception e) {
                    if (!stopped) {
                        // log.warn("Failed to obtain messages from queue.", e);
                        try {
                            Thread.sleep(pollDuration);
                        } catch (InterruptedException e2) {
                            // log.trace("Failed to wait until the server has capacity to handle new requests", e2);
                        }
                    }
                }
            }
            log.info(" Core Consumer stopped.");
        });
    }

    @Override
    protected void stopMainConsumers() {
        if (mainConsumer != null) {
            mainConsumer.unsubscribe();
        }

    }

    @Override
    protected void launchConsumersList() {
        log.info("启动消费线程组！");
        consumerList.stream().forEach(consumer -> {
            log.info("channel number:{}"+consumer.getChannelNumber());
            consumersExecutor.submit(() -> {
                while (!stopped) {
                    try {
                        List<TbQueueMsg> msgs = consumer.poll(pollDuration);
                        if (msgs.isEmpty()) {
                            continue;
                        }
                        for (TbQueueMsg item : msgs) {
                            comsureQueue.offer(item);
                        }

                        consumer.commit();
                    } catch (Exception e) {
                        if (!stopped) {
                            try {
                                Thread.sleep(pollDuration);
                            } catch (InterruptedException e2) {
                                log.trace("Failed to wait until the server has capacity to handle new requests", e2);
                            }
                        }
                    }
                }
            });
        });
    }

}
