package com.qmth.themis.business.service.impl;

import java.util.Collections;

import javax.annotation.Resource;

import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

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.util.JacksonUtil;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;

/**
 * @Description: mq 服务实现类
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/28
 */
@Service
public class ProducerServerImpl implements ProducerServer {
    private final static Logger log = LoggerFactory.getLogger(ProducerServerImpl.class);

    @Resource
    RocketMQTemplate rocketMQTemplate;

    /**
     * 同步消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result syncMsg(MqDto mqDto) {
        log.info("syncMsg mqDto:{}", JacksonUtil.parseJson(mqDto));
        SendResult sendResult = rocketMQTemplate.syncSend(mqDto.getTopic() + ":" + mqDto.getTag(), mqDto);
        // 同步消息发送成功会有一个返回值，我们可以用这个返回值进行判断和获取一些信息
        log.info("sendResult:{}", JacksonUtil.parseJson(sendResult));
        return ResultUtil.ok(true);
    }

    /**
     * 同步顺序消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result syncOrderlyMsg(MqDto mqDto) {
        log.info("syncOrderlyMsg mqDto:{}", JacksonUtil.parseJson(mqDto));
        SendResult sendResult = rocketMQTemplate.syncSendOrderly(mqDto.getTopic() + ":" + mqDto.getTag(), mqDto, mqDto.getObjId());
        // 同步顺序消息发送成功会有一个返回值，我们可以用这个返回值进行判断和获取一些信息
        log.info("sendResult:{}", JacksonUtil.parseJson(sendResult));
        return ResultUtil.ok(true);
    }

    /**
     * 同步延时消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result syncDelayMsg(MqDto mqDto) {
        log.info("syncDelayMsg mqDto:{}", JacksonUtil.parseJson(mqDto));
//        Message message = assembleMessage(mqDto);
        org.springframework.messaging.Message messageTran = MessageBuilder.withPayload(mqDto).build();
        rocketMQTemplate.syncSend(mqDto.getTopic() + ":" + mqDto.getTag(), messageTran, SystemConstant.MESSAGE_TIMEOUT, Integer.parseInt(String.valueOf(mqDto.getProperties().get("timeOut"))));
        return ResultUtil.ok(true);
    }

    /**
     * 异步消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result asyncMsg(MqDto mqDto) {
        log.info("asyncMsg mqDto:{}", JacksonUtil.parseJson(mqDto));
        rocketMQTemplate.asyncSend(mqDto.getTopic() + ":" + mqDto.getTag(), mqDto, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                // 成功回调
                log.info("sendResult:{}", JacksonUtil.parseJson(sendResult));
            }

            @Override
            public void onException(Throwable throwable) {
                // 失败回调
                throw new BusinessException(throwable.getMessage());
            }
        });
        return ResultUtil.ok(true);
    }

    /**
     * 异步顺序消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result asyncOrderlyMsg(MqDto mqDto) {
        log.info("asyncOrderlyMsg mqDto:{}", JacksonUtil.parseJson(mqDto));
        rocketMQTemplate.asyncSendOrderly(mqDto.getTopic() + ":" + mqDto.getTag(), mqDto, mqDto.getObjId(), new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                // 成功回调
                log.info("sendResult:{}", JacksonUtil.parseJson(sendResult));
            }

            @Override
            public void onException(Throwable throwable) {
                // 失败回调
                throw new BusinessException(throwable.getMessage());
            }
        });
        return ResultUtil.ok(true);
    }

    /**
     * 异步延时消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result asyncDelayMsg(MqDto mqDto) {
        log.info("asyncDelayMsg mqDto:{}", JacksonUtil.parseJson(mqDto));
//        Message message = assembleMessage(mqDto);
        org.springframework.messaging.Message messageTran = MessageBuilder.withPayload(mqDto).build();
        rocketMQTemplate.asyncSend(mqDto.getTopic() + ":" + mqDto.getTag(), messageTran, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                // 成功回调
                log.info("sendResult:{}", JacksonUtil.parseJson(sendResult));
            }

            @Override
            public void onException(Throwable throwable) {
                // 失败回调
                throw new BusinessException(throwable.getMessage());
            }
        }, SystemConstant.MESSAGE_TIMEOUT, Integer.parseInt(String.valueOf(mqDto.getProperties().get("timeOut"))));
        return ResultUtil.ok(true);
    }

    /**
     * 单向消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result sendOneWay(MqDto mqDto) {
        log.info("sendOneWay mqDto:{}", JacksonUtil.parseJson(mqDto));
        rocketMQTemplate.sendOneWay(mqDto.getTopic() + ":" + mqDto.getTag(), mqDto);
        return ResultUtil.ok(true);
    }

    /**
     * 单向顺序消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result sendOneWayOrderly(MqDto mqDto) {
        log.info("sendOneWayOrderly mqDto:{}", JacksonUtil.parseJson(mqDto));
        rocketMQTemplate.sendOneWayOrderly(mqDto.getTopic() + ":" + mqDto.getTag(), mqDto, mqDto.getObjId());
        return ResultUtil.ok(true);
    }

    /**
     * 事务消息
     *
     * @param mqDto
     * @return
     */
    @Override
    public Result sendMsgTran(MqDto mqDto) {
        log.info("sendMsgTran mqDto:{}", JacksonUtil.parseJson(mqDto));
//        Message message = assembleMessage(mqDto);
        org.springframework.messaging.Message messageTran = MessageBuilder.withPayload(mqDto).build();
        //发送事务消息
        TransactionSendResult transactionSendResult = rocketMQTemplate.sendMessageInTransaction(mqDto.getTopic() + ":" + mqDto.getTag(), messageTran, null);
        log.info("transactionSendResult:{}", JacksonUtil.parseJson(transactionSendResult));
        return ResultUtil.ok(true);
    }

    /**
     * 组装message
     *
     * @param mqDto
     * @return
     */
//    public Message assembleMessage(MqDto mqDto) {
//        Message message = new Message();
//        message.setTopic(mqDto.getTopic());
//        message.setBody(String.valueOf(mqDto.getBody()).getBytes());
//        message.setTags(mqDto.getTag());
//        message.putUserProperty(SystemConstant.MQDTO_OBJ, JacksonUtil.parseJson(mqDto));
//        return message;
//    }
}
