package com.atliwen.server.messagelistener;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import com.alibaba.rocketmq.client.producer.SendResult;
import com.alibaba.rocketmq.common.message.MessageExt;
import com.currencyboot.domain.mq.HttpResponse;
import com.currencyboot.service.rocketmq.MqProducer;
import com.currencyboot.service.rocketmq.common.ForwardedHelp;
import com.currencyboot.service.rocketmq.common.HttpRequest;
import com.currencyboot.service.rocketmq.messagelistener.Interface.ExternalCallConsumerInterface;
import com.currencyboot.service.rocketmq.messagelistener.Interface.MatchingInterface;
import com.currencyboot.service.rocketmq.messagelistener.Interface.MessageListenerConsumerInterface;

/**
* <p>Title: ExternalCallConcurrentlyStatus </p>
* <p>@Description: web服务调用 消费端  </p>
* <p>Company:  </p>
* @author 李文
* @date   2016年8月1日 上午10:09:59 
*/
public class ExternalCallConcurrentlyStatus implements MessageListenerConsumerInterface
{

	private static final Logger LOGGER = LoggerFactory
			.getLogger(ExternalCallConcurrentlyStatus.class);

	/**
	 *    验证规则
	 *    
	 *    list
	 *    		map
	 *    			Tag =  test1,test2,test3
	 *    			body=  客户编码A,客户编码B
	 *    			url = http://10.10.12.27
	 *    	
	 */
	private List<Map<String, String>> matching;

	/**
	 *  数据字符集
	 */
	@Value("${MQ.Encoding:UTF-8}")
	private String Encoding;

	/**
	 *  转译  实体数据
	 */
	private ExternalCallConsumerInterface externalCall;

	/**
	 * 验证规则数据源获取接口
	 */
	private MatchingInterface baseMatching;

	/**
	 * 转发模式
	 */
	private ForwardedMessageListConsumer forwarded;

	/**
	 *  生产端
	 */
	@Autowired(required = false)
	private MqProducer producer;

	@Override
	public ConsumeConcurrentlyStatus consumeMessage(String strBody, MessageExt msg,
			ConsumeConcurrentlyContext context)
	{

		if (baseMatching != null)
		{
			List<Map<String, String>> me = baseMatching.getMatching();
			if (me != null && me.size() != 0) matching = me;
		}

		// TODO 待完善 日志系统 最简单的方法是 使用 mongodb 存放日志数据
		for (Map<String, String> map : matching)
		{
			Map<String, String> params = new HashMap<String, String>();

			params.put("Topic", msg.getTopic());
			params.put("Tags", msg.getTags());

			if (externalCall == null) params.put("Body", strBody);
			else params.put("Body", externalCall.MessageConsumer(strBody, msg, context));

			return sendMqTags(map, msg.getTags(), params, strBody, msg, context);
		}
		return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;

	}

	/**
	 *    验证规则 并按照规则将数据 转发到对应的 队列中  
	 */
	public ConsumeConcurrentlyStatus sendMqTags(Map<String, String> matchingMap, String MqTags,
			Map<String, String> params, String strBody, MessageExt msg,
			ConsumeConcurrentlyContext context)
	{
		// 验证是否有空值
		String[] keys =
		{ "url", "Tag", "body" };
		try
		{
			ForwardedHelp.outStr(matchingMap, keys);
		}
		catch (Exception e)
		{
			LOGGER.error(e.getMessage());
			return ConsumeConcurrentlyStatus.RECONSUME_LATER;
		}

		return forwardedWebDate(matchingMap, MqTags, params, msg, context);

	}

	/**
	 * 外调 Web API 后续结果 继续转发       转发类  权级 》 XML 配置权级
	 * @param matchingMap
	 * @param MqTags
	 * @param params
	 * @param msg
	 * @param context
	 * @return
	 */
	private ConsumeConcurrentlyStatus forwardedWebDate(Map<String, String> matchingMap,
			String MqTags, Map<String, String> params, MessageExt msg,
			ConsumeConcurrentlyContext context)
	{
		HttpResponse response = equalsTag(matchingMap, MqTags, params);
		if (response.getState() == 202) { return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; }
		if (response.getState() != 200) { return ConsumeConcurrentlyStatus.RECONSUME_LATER; }
		if (forwarded != null) { return forwarded.consumeMessage(response.getData(), msg,
				context); }

		String[] keyszf =
		{ "Topic", "Tags" };
		try
		{
			ForwardedHelp.outStr(matchingMap, keyszf);
		}
		catch (Exception e)
		{
			// LOGGER.debug(" 外调Web API 后续不进行转发 消息 body= " +
			// response.getData());
			LOGGER.error("外调Web API 后续不进行转发 消息 body= " + response.getData() + " " + e.getMessage());
			return ConsumeConcurrentlyStatus.RECONSUME_LATER;
		}

		try
		{
			if (producer == null)
			{
				LOGGER.error("  外调后续转发 发送失败   , 并未配置  生产者 ");
				return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
			}

			SendResult se = producer.send(matchingMap.get("Topic"), matchingMap.get("Tags"),
					response.getData());
			if (se == null)
			{
				LOGGER.error(" 外调后续转发 发送失败 。需要转发的数据   Topic=" + matchingMap.get("Topic") + "  Tags="
						+ matchingMap.get("Tags") + "  data" + response.getData());
				return ConsumeConcurrentlyStatus.RECONSUME_LATER;
			}
		}
		catch (Exception e)
		{

			LOGGER.error(" 外调 异常 转发消息到MQ  失败  Tag= " + matchingMap.get("Topic") + " body= "
					+ response.getData(), e);
			return ConsumeConcurrentlyStatus.RECONSUME_LATER;
		}
		return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
	}

	/**
	 *   匹配 Tag 消息 Tag 的验证
	 *   
	 * @param matchingMap   注入的  匹配 规则 数据
	 * @param MqTags        当前消费的MQ  Tags
	 * @param Mqbody		当前转发的 消息 实体
	 * @param Topic			需要转发到的 MQ Topic
	 * @return
	 */
	private HttpResponse equalsTag(Map<String, String> matchingMap, String MqTags,
			Map<String, String> params)
	{
		String url = matchingMap.get("url");

		// 是否需要 匹配 Tag
		if ("*".equals(matchingMap.get("Tag")))
		{
			// 不需要匹配
			// 匹配 body
			return equalsbody(matchingMap, MqTags, url, params);

		}
		else
		{
			// 进行匹配 Tag
			if (ForwardedHelp.isContains(MqTags, matchingMap.get("Tag")))
			{
				// 匹配成功 进行 匹配 body
				return equalsbody(matchingMap, MqTags, url, params);
			}
			else
			{
				LOGGER.debug("Tag 匹配未成功 放弃该消息    消息内容是   " + MqTags);
				return new HttpResponse(202, "body Tag 匹配未成功 放弃该消息");
			}
		}
	}

	/**
	 *   匹配 body 消息实体的验证
	 *   
	 * @param matchingMap   注入的  匹配 规则 数据
	 * @param MqTags        当前消费的MQ  Tags
	 * @param Mqbody		当前转发的 消息 实体
	 * @param Topic			需要转发到的 MQ Topic
	 * @return
	 */
	private HttpResponse equalsbody(Map<String, String> matchingMap, String MqTags, String url,
			Map<String, String> params)
	{
		// 匹配 body
		if ("*".equals(matchingMap.get("body")))
		{
			// 不需要 匹配 Tag
			return sendMq(matchingMap, url, params);
		}

		if (!ForwardedHelp.isContains(params.get("body"), matchingMap.get("body")))
		{
			LOGGER.debug("body 匹配未成功 放弃该消息    消息内容是   " + MqTags);
			return new HttpResponse(200, "body 匹配未成功 放弃该消息");
		}
		else
		{
			// 不需要 匹配 Tag
			return sendMq(matchingMap, url, params);
		}
	}

	/**
	 * @param matchingMap
	 * @param mqbody
	 * @param url
	 * @return
	 */
	private HttpResponse sendMq(Map<String, String> matchingMap, String url,
			Map<String, String> params)
	{

		return HttpRequest.sendPostMessage(url, params, Encoding);
	}

	/**  
	 * 设置验证规则listmapTag=test1test2test3body=客户编码A,客户编码Burl  
	 * @param matching 验证规则listmapTag=test1test2test3body=客户编码A,客户编码Burl  
	 */
	public void setMatching(List<Map<String, String>> matching)
	{
		this.matching = matching;
	}

	/**  
	 * 设置转译实体数据  
	 * @param externalCall 转译实体数据  
	 */
	public void setExternalCall(ExternalCallConsumerInterface externalCall)
	{
		this.externalCall = externalCall;
	}

	/**
	 * @param 转发模式 the forwarded to set
	 */
	public void setForwarded(ForwardedMessageListConsumer forwarded)
	{
		this.forwarded = forwarded;
	}

	/**  
	 * 设置验证规则数据源获取接口  
	 * @param baseMatching 验证规则数据源获取接口  
	 */
	public void setBaseMatching(MatchingInterface baseMatching)
	{
		this.baseMatching = baseMatching;
	}

}