package com.elab.mq.msg.impl;

import com.aliyun.openservices.ons.api.SendResult;
import com.aliyun.openservices.ons.api.bean.ProducerBean;
import com.elab.core.utils.StringUtils;
import com.elab.log.utils.CatCrossProcess;
import com.elab.mq.listener.LoggerConsumerInterceptor;
import com.elab.mq.model.MessageModel;
import com.elab.mq.model.SendResultModel;
import com.elab.mq.msg.IMsgProducerFacade;
import com.elab.mq.msg.ProducerInterceptor;
import com.elab.mq.msg.adptor.SendCallbackAdaptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.Properties;

/**
 * 消息生产包装类
 *
 * @author Liukx
 * @create 2018-04-09 18:23
 * @email liukx@elab-plus.com
 **/
public class MsgProducerImpl extends ProducerBean implements IMsgProducerFacade {

    private Logger logger = LoggerFactory.getLogger(MsgProducerImpl.class);

    @Autowired(required = false)
    private ProducerInterceptor producerInterceptor = new LoggerConsumerInterceptor();

    private final String MQ_PRODUCER = "MQ_PRODUCER";

    @Override
    public void sendAsync(MessageModel message, SendCallbackAdaptor sendCallback) {
        logger.debug(" 发送一条异步消息 " + message + " -> " + message.toString() + " 回调类 : " + sendCallback.getClass().getName());
        super.sendAsync(message, sendCallback);
    }

    @Override
    public SendResultModel send(MessageModel message) {
        String topic = message.getTopic();
        String tag = message.getTag();

        String key = message.getKey();
        if (StringUtils.isNotEmpty(key)) {
            logger.warn("请填相应的key，方便定位该数据");
        }

        Object msgResult = CatCrossProcess.createRemoteMQMsg(MQ_PRODUCER, topic + "_" + tag + "_" + getClass().getSimpleName(), (idMap) -> {
            logger.debug(" 发送一条消息 " + message.getMsgID() + " -> " + message.toString());

            // 提前插入消息，为了让消息编号能够带过去，如果发送失败，则根据编号更改为-1状态。
            // int id = insertRecordProducer(message);
            long start = System.currentTimeMillis();
            try {

                idMap.forEach((K, V) -> {
                    message.putUserProperties(K, V);
                });

                boolean check = producerInterceptor.check(message, message.getModuleName());

                if (!check) {
                    return null;
                }

                SendResult result = super.send(message);
                long time = System.currentTimeMillis() - start;
                message.setInvokeTime(time);
                logger.debug(" 消息发送结果 : " + result.toString());

                producerInterceptor.success(message, message.getModuleName(), result);
                return new SendResultModel(result);
            } catch (Exception e) {
                logger.error("消息发送异常", e);
                long time = System.currentTimeMillis() - start;
                message.setInvokeTime(time);
                producerInterceptor.error(message, message.getModuleName(), e);
                throw e;
            }
        });
        if (msgResult != null) {
            return (SendResultModel) msgResult;
        }
        return null;
    }

    @Override
    public void sendOneway(MessageModel message) {
        logger.debug(" 发送一条单向消息 " + message.getMsgID() + " -> " + message.toString());
        super.sendOneway(message);
    }

    @Override
    public SendResultModel sendDeliverTime(MessageModel messageModel, int seconds) {
        logger.debug(" 发送一条延时消息 : 将在[" + seconds + "]秒后发送 , 消息内容 : " + messageModel.toString());
        long time = System.currentTimeMillis() + (seconds * 1000);
        messageModel.setStartDeliverTime(time);
        return send(messageModel);
    }

    @Override
    public SendResultModel sendTimingMsg(MessageModel messageModel, Date datetime) {
        logger.debug(" 发送一条定时消息 : 将在[" + datetime + "]后发送 , 消息内容 : " + messageModel.toString());
        messageModel.setStartDeliverTime(datetime.getTime());
        return send(messageModel);
    }

    @Override
    public void setProperties(Properties properties) {
        super.setProperties(properties);
    }

}
