package com.crm.rely.backend.service.impl;

import com.alibaba.fastjson.JSON;
import com.crm.rely.backend.service.MqSendService;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.ScheduledMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;

import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.TextMessage;

/**
 * @program: user-custom
 * @description: mq统一发送
 * @author: houn
 * @create: 2019-05-22 09:41
 */
@Slf4j
@Service
public class MqSendServiceImpl implements MqSendService {

    @Autowired
    private JmsTemplate jmsTemplate;

    /**
     * 发送消息(毫秒)
     *
     * @param queue 队列
     * @param msg   消息内容
     */
    @Override
    public void send(Queue queue, String msg) {

        write(queue, msg, 0);
        jmsTemplate.convertAndSend(queue, msg);
    }

    @Override
    public void send(Queue queue, Object msg) {
        send(queue, JSON.toJSONString(msg));
    }

    /**
     * 发送消息(毫秒)
     *
     * @param queueName 队列url(名称)
     * @param msg       消息内容
     */
    @Override
    public void send(String queueName, String msg) {

        write(queueName, msg, 0);
        jmsTemplate.convertAndSend(queueName, msg);

    }

    @Override
    public void send(String queueName, Object msg) {
        send(queueName, JSON.toJSONString(msg));
    }

    /**
     * 发送延迟消息(毫秒)
     *
     * @param queue 队列
     * @param msg   消息内容
     * @param delay 延迟时间
     */
    @Override
    public void send(Queue queue, String msg, long delay) {

        write(queue, msg, delay);

        jmsTemplate.send(queue, getMessageCreator(msg, delay));

    }

    @Override
    public void send(Queue queue, Object msg, long delay) {
        send(queue, JSON.toJSONString(msg), delay);
    }

    /**
     * 发送延迟消息(毫秒)
     *
     * @param queueName 队列url(名称)
     * @param msg       消息内容
     * @param delay     延迟时间
     */
    @Override
    public void send(String queueName, String msg, long delay) {

        write(queueName, msg, delay);

        jmsTemplate.send(queueName, getMessageCreator(msg, delay));

    }

    @Override
    public void send(String queueName, Object msg, long delay) {
        send(queueName, JSON.toJSONString(msg), delay);
    }

    private MessageCreator getMessageCreator(String msg, long delay) {

        return session -> {
            TextMessage tm = session.createTextMessage(msg);
            tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
            tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1 * 1000);
            tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1);
            return tm;
        };
    }

    /**
     * 获取队列名称
     *
     * @param queue
     * @return
     */
    private String getQueueName(Queue queue) {

        String queueName;
        try {
            queueName = queue.getQueueName();
        } catch (JMSException e) {
            log.error(e.getMessage());
            queueName = "";
        }
        return queueName;
    }

    /**
     * 打印发送日志
     *
     * @param queue
     * @param msg
     * @param delay
     */
    private void write(Queue queue, String msg, long delay) {

        String queueName = getQueueName(queue);
        write(queueName, msg, delay);
    }

    /**
     * 打印发送日志
     *
     * @param queueName 队列名
     * @param msg       消息内容
     * @param delay     延迟时间 0为非延时
     */
    private void write(String queueName, String msg, long delay) {
        validateParams(queueName, msg);
        if (delay <= 0) {

            log.info("发送MQ即时消息: queueName={}, msg={}", queueName, msg);
        } else {
            log.info("发送MQ延时消息: queueName={}, msg={}, delay={}ms", queueName, msg, delay);
        }
    }

    private void validateParams(Object queueOrName, String msg) {
        if (queueOrName == null || msg == null || msg.trim().isEmpty()) {
            throw new IllegalArgumentException("Queue/QueueName or message cannot be null or empty");
        }
    }
}
