package com.neusoft.smart.pos.mq.aliyunRocketMq;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.ONSFactory;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.SendResult;
import com.neusoft.smart.pos.mq.MQConfig;
import com.neusoft.smart.pos.mq.MqProducer;
import com.neusoft.smart.pos.mq.util.JsonUtil;


/**
 * @Auther: zfy  阿里云rocketmq
 * @Date: 2019-01-31
 * @Description: RocketMQ消息生产者
 */
@Service
@Profile(MQConfig.Impl.ALIYUN_ROCKET_MQ)
public class AliyunRocketMqMessageProducer implements MqProducer {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    
    @Value("${spring.aliyunRocketmq.accessKeyId}")
    private String accessKeyId;
    
    @Value("${spring.aliyunRocketmq.accessKeySecret}")
    private String accessKeySecret;
    
    @Value("${spring.aliyunRocketmq.namesrvAddr}")
    private String namesrvAddr;
    
    //@Autowired
    //private WxMsgRecordMapper wxMsgRecordMapper;

    //@Autowired
    //private WxMsgRecordService wxMsgRecordService;

    private static Map<String,Producer> producerMap = null;
    
   @PostConstruct
   public void init() {
	   producerMap = new HashMap<String,Producer>();
	   for (EnumMsgTopic topic: EnumMsgTopic.values()) {
		   Properties properties = new Properties();
	       properties.setProperty(PropertyKeyConst.GROUP_ID, topic.getGroupId());
	       // AccessKey 阿里云身份验证，在阿里云服务器管理控制台创建
	       properties.put(PropertyKeyConst.AccessKey,accessKeyId);
	       // SecretKey 阿里云身份验证，在阿里云服务器管理控制台创建
	       properties.put(PropertyKeyConst.SecretKey, accessKeySecret);
	       //设置发送超时时间，单位毫秒
	       properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000");
	       // 设置 TCP 接入域名，到控制台的实例基本信息中查看
	       properties.put(PropertyKeyConst.NAMESRV_ADDR,namesrvAddr);
	       Producer producer = ONSFactory.createProducer(properties);
		// 在发送消息前，必须调用 start 方法来启动 Producer，只需调用一次即可
	       producer.start();
	       log.info("aliyunrocketmq producer info :"+JSON.toJSONString(producer));
	       producerMap.put(topic.getTopic(), producer);
	   }
	   
   }
   
    @Override
    public void sendMessage(String exchange, String routingKey, Serializable object) {
    	sendStringMsg(exchange,JsonUtil.obj2Json(object));
    }

	@Override
	public void sendMessage(String exchange, String routingKey, String msg) {
		sendStringMsg(exchange,msg);
	}
	
	private void sendStringMsg(String topic,String content) {
    	Producer producer = producerMap.get(topic);
    	if (null == producer) {
    		log.error("topic :"+topic+" has no AliyunRocketMqMessageProducer.");
    		return;
    	}
    	if (producer.isClosed()) {
    		producer.start();
    	}
    	List<EnumMsgTopicTags> topicTags = EnumMsgTopicTags.getTagsByTopic(topic);
    	if (null != topicTags) {
    		for (EnumMsgTopicTags emtt:topicTags) {
    			//循环发送消息
                Message msg = new Message( //
                    // Message 所属的 Topic
                	topic,
                    // Message Tag 可理解为 Gmail 中的标签，对消息进行再归类，方便 Consumer 指定过滤条件在 MQ 服务器过滤
                	emtt.getTags(),
                    // Message Body 可以是任何二进制形式的数据， MQ 不做任何干预，
                    // 需要 Producer 与 Consumer 协商好一致的序列化和反序列化方式
                	content.getBytes());
                // 设置代表消息的业务关键属性，请尽可能全局唯一。
                // 以方便您在无法正常收到消息情况下，可通过阿里云服务器管理控制台查询消息并补发
                // 注意：不设置也不会影响消息正常收发
                //msg.setKey(routingKey);
                msg.setKey(emtt.getTags());

                try {
                    SendResult sendResult = producer.send(msg);
                    // 同步发送消息，只要不抛异常就是成功
                    if (sendResult != null) {
                    	log.info(new Date() + " Send mq message success. Topic is:" + msg.getTopic() + " msgId is: " + sendResult.getMessageId());
                    }
                }
                catch (Exception e) {
                    // 消息发送失败，需要进行重试处理，可重新发送这条消息或持久化这条数据进行补偿处理
                	log.error(new Date() + " Send mq message failed. Topic is:" + msg.getTopic(),e);
                }
    		}
    	}

        // 在应用退出前，销毁 Producer 对象
        // 注意：如果不销毁也没有问题
        //producer.shutdown();
	}
}
