package com.liquidnet.common.mq.handle;

import com.alibaba.fastjson.JSONObject;
import com.liquidnet.common.mq.constant.GlobalConstant;
import com.liquidnet.common.mq.util.JAXBUtil;
import com.liquidnet.common.mq.util.ObjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

/**
 * Created by guo_x on 2016/11/19.
 */
@Component
public class SendMQ implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
    Logger logger = LoggerFactory.getLogger(SendMQ.class);

    private RabbitTemplate rabbitTemplate;

    /**
     * 构造方法注入
     */
    @Autowired
    public SendMQ(@Qualifier("rabbitTemplate") RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        rabbitTemplate.setReturnCallback(this);
        rabbitTemplate.setConfirmCallback(this);//rabbitTemplate如果为单例的话，那回调就是最后设置的内容

    }


    /**
     * request/response模式
     *
     * @param key
     * @param content
     * @param id
     * @param type
     * @param c
     * @param <T>
     * @return
     */
    public <T> T sendMsgAndReceive(String key, Object content, String id, String type, Class<T> c) {
        String sendContent = "";
        switch (type) {
            case GlobalConstant.JSON:
                sendContent = JSONObject.toJSONString(content);
                break;
            case GlobalConstant.XML:
                sendContent = JAXBUtil.convertToXml(content);
                break;
            default:
                sendContent = JSONObject.toJSONString(content);
        }
        T receiveMsg = null;
        CorrelationData correlationId = new CorrelationData(id);

        logger.info("[synchronization]sendMsgAndReceive:id[{}],exchange[{}],routingKey[{}],message[{}]", correlationId.getId(), rabbitTemplate.getExchange(), key, content);
        Object obj = rabbitTemplate.convertSendAndReceive(rabbitTemplate.getExchange(), key, content, correlationId);
        receiveMsg = ObjectUtil.converyToBean(obj, c);

        logger.info("[synchronization]sendMsgAndReceive:id[{}],exchange[{}],routingKey[{}],message[{}],result[{}]", correlationId.getId(), rabbitTemplate.getExchange(), key, content, obj);
        return receiveMsg;
    }

    public void sendMsg(String key, Object content, String id, String type) {
        String sendContent = convertContent(content, type);
        sendMsg(key, sendContent, id);
    }

    public void sendMsg(String key, String content, String id) {
        CorrelationData correlationId = new CorrelationData(id);
        logger.info("[asynchronous]sendMsg:id[{}],exchange[{}],routingKey[{}],message[{}]", correlationId.getId(), rabbitTemplate.getExchange(), key, content);
        try {
            rabbitTemplate.convertAndSend(rabbitTemplate.getExchange(), key, content, correlationId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected String convertContent(Object content, String type) {
        String sendContent = "";
        switch (type) {
            case GlobalConstant.JSON:
                sendContent = JSONObject.toJSONString(content);
                break;
            case GlobalConstant.XML:
                sendContent = JAXBUtil.convertToXml(content);
                break;
            default:
                sendContent = JSONObject.toJSONString(content);
        }
        return sendContent;
    }


    /**
     * 回调
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {

    }

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        logger.info("returnback:{}", replyCode);
        try {
            Thread.sleep(GlobalConstant.ONE_SECOND);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
