package com.qmth.themis.task.quartz;

import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.service.ProducerServer;
import com.qmth.themis.business.service.TMRocketMessageService;
import com.qmth.themis.business.util.RedisUtil;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;

/**
 * @Description: mq job
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/7/1
 */
public class MqJob extends QuartzJobBean {
    private final static Logger log = LoggerFactory.getLogger(MqJob.class);

    @Resource
    RedisUtil redisUtil;

    @Resource
    ProducerServer producerServer;

    @Resource
    TMRocketMessageService tmRocketMessageService;

    @Override
    protected void executeInternal(JobExecutionContext context) {
        log.info("mq_job进来了,context:{}", context);
        this.assembleJob(SystemConstant.MQ_TOPIC_BUFFER_LIST);
        log.info("mq_delay_job进来了,context:{}", context);
        this.assembleDelayJob(SystemConstant.MQ_DELAY_TOPIC_BUFFER_LIST);
        log.info("mq_broadcast_job进来了,context:{}", context);
        this.assembleBroadCastJob(SystemConstant.MQ_BROADCAST_TOPIC_BUFFER_LIST);
    }

    /**
     * 组装job
     *
     * @param redisKey
     */
    public void assembleJob(String redisKey) {
        Long size = redisUtil.getHashSize(redisKey);
        if (Objects.nonNull(size) && size.longValue() > 0) {
            log.info("redisKey:{}缓冲区的消息数为:{}", redisKey, size);
            Map map = redisUtil.getHashEntries(redisKey);
            map.forEach((k, v) -> {
                MqDto mqDto = (MqDto) v;
                if (mqDto.getReconsume() >= SystemConstant.MAXRECONSUMETIMES) {
                    tmRocketMessageService.saveMqMessageError(mqDto, redisKey);
                } else {
                    mqDto.setReconsume(mqDto.getReconsume() + 1);
                    redisUtil.set(redisKey, mqDto.getId(), mqDto);
                    producerServer.asyncMsg(mqDto);
                }
            });
        }
    }

    /**
     * 组装延时job
     *
     * @param redisKey
     */
    public void assembleDelayJob(String redisKey) {
        Long size = redisUtil.getHashSize(redisKey);
        if (Objects.nonNull(size) && size.longValue() > 0) {
            log.info("redisKey:{}缓冲区的消息数为:{}", redisKey, size);
            Map map = redisUtil.getHashEntries(redisKey);
            map.forEach((k, v) -> {
                MqDto mqDto = (MqDto) v;
                if (mqDto.getReconsume() >= SystemConstant.MAXRECONSUMETIMES) {
                    tmRocketMessageService.saveMqMessageError(mqDto, redisKey);
                } else {
                    Map<String, Object> prop = mqDto.getProperties();
                    Long mqExecTime = Long.parseLong(String.valueOf(prop.get("mqExecTime")));
                    //mq为延时消息，所以每分钟扫描时有可能mq消息还未执行，所以加上mq消息等级和当前时间对比，如超过mq的延时时间一分钟则执行
                    if (Objects.nonNull(mqExecTime) && (mqExecTime - System.currentTimeMillis()) / 1000 / 60 <= -1) {
                        mqDto.setReconsume(mqDto.getReconsume() + 1);
                        redisUtil.set(redisKey, mqDto.getId(), mqDto);
                        producerServer.asyncMsg(mqDto);
                    }
                }
            });
        }
    }

    /**
     * 组装广播job
     *
     * @param redisKey
     */
    public void assembleBroadCastJob(String redisKey) {
        Long size = redisUtil.getHashSize(redisKey);
        if (Objects.nonNull(size) && size.longValue() > 0) {
            log.info("redisKey:{}缓冲区的消息数为:{}", redisKey, size);
            Map map = redisUtil.getHashEntries(redisKey);
            map.forEach((k, v) -> {
                MqDto mqDto = (MqDto) v;
                if (mqDto.getReconsume() >= SystemConstant.MAXRECONSUMETIMES) {
                    tmRocketMessageService.saveMqMessageError(mqDto, redisKey);
                } else {
                    mqDto.setReconsume(mqDto.getReconsume() + 1);
                    redisUtil.set(redisKey, mqDto.getId(), mqDto);
                    producerServer.asyncMsg(mqDto);
                }
            });
        }
    }
}
