package cn.hmsoft.weixin.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import cn.hmsoft.application.SpringHelper;
import cn.hmsoft.helper.JsonHelper;
import cn.hmsoft.helper.StringHelper;
import cn.hmsoft.log.LogHelper;
import cn.hmsoft.weixin.data.dao.WxTemplateLogDao;
import cn.hmsoft.weixin.data.model.WxDefine;
import cn.hmsoft.weixin.data.model.WxTemplate;
import cn.hmsoft.weixin.data.model.WxTemplateLog;
import cn.hmsoft.weixin.entity.request.TemplateRequestEntity;
import cn.hmsoft.weixin.entity.request.TemplateSendRequestJson;
import cn.hmsoft.weixin.entity.response.WxResponseJson;
import cn.hmsoft.weixin.request.TemplateSendRequest;

/**********************************************
 * 微信模版消息类
 * 
 * @author: Zhang XiaoQing
 * @date: 2017-08-28 21:52:48
 * @version: 4.0.0
 * @email: revisit@126.com
 * @Company: www.hmsoft.cn
 */
public abstract class WeiXinTemplateUtil {

	/*********************************
	 * 根据配置的业务类型发送微信消息
	 */
	public static void sendWeiXinTemplate(String app_id, String open_id, String business_type,
			Map<String, Object> valueMap) {
		sendWeiXinTemplate(app_id, open_id, business_type, valueMap, true);
	}

	/*********************************
	 * 根据配置的业务类型发送微信消息
	 */
	public static void sendWeiXinTemplate(String app_id, String open_id, String business_type,
			Map<String, Object> valueMap, boolean thread_flag) {
		if (StringHelper.isEmpty(business_type) || StringHelper.isEmpty(open_id))
			return;
		WxDefine wx = null;
		try {
			wx = WeiXinUtil.getWxDefine(app_id);
		} catch (Exception e) {
			return;
		}
		// 不需要发送模版消息
		if (!wx.getTemplateMap().containsKey(business_type) || wx.getTemplateMap().get(business_type).size() == 0)
			return;
		// TemplateRequestEntity entity =new TemplateRequestEntity(template_id,
		// open_id, title, content)
		for (WxTemplate template : wx.getTemplateMap().get(business_type)) {
			WxTemplate sendTemplate = new WxTemplate();
			// 逐一发送
			if (valueMap != null) {
				// 替换url
				sendTemplate.setTemplate_url(
						replaceValues(template.getTemplateUrlMap(), valueMap, template.getTemplate_url()));
				// 替换first
				sendTemplate.setContent_value(
						replaceValues(template.getFirstValueMap(), valueMap, template.getContent_value()));

				// 替换keyword1
				sendTemplate.setKeyword1_value(
						replaceValues(template.getKeyword1ValueMap(), valueMap, template.getKeyword1_value()));

				// 替换keyword2
				sendTemplate.setKeyword2_value(
						replaceValues(template.getKeyword2ValueMap(), valueMap, template.getKeyword2_value()));

				// 替换keyword3
				sendTemplate.setKeyword3_value(
						replaceValues(template.getKeyword3ValueMap(), valueMap, template.getKeyword3_value()));

				// 替换keyword4
				sendTemplate.setKeyword4_value(
						replaceValues(template.getKeyword4ValueMap(), valueMap, template.getKeyword4_value()));

				// 替换keyword5
				sendTemplate.setKeyword5_value(
						replaceValues(template.getKeyword5ValueMap(), valueMap, template.getKeyword5_value()));
				// 替换remark
				sendTemplate.setRemark_value(
						replaceValues(template.getRemarkValueMap(), valueMap, template.getRemark_value()));

				TemplateRequestEntity entity = new TemplateRequestEntity(template.getTemplate_code(), open_id,
						sendTemplate.getContent_value(), sendTemplate.getKeyword1_value());
				entity.setTopcolor(template.getTop_color());
				entity.setFirst_color(template.getContent_color());
				// url有特殊字符，直接替换
				if(valueMap.containsKey("RealTemplateUrl")) {
					entity.setUrl(valueMap.get("RealTemplateUrl").toString());
				} else 
					entity.setUrl(sendTemplate.getTemplate_url());
				
				entity.setKeyword1_color(template.getKeyword1_color());
				entity.setKeyword2_color(template.getKeyword2_color());
				entity.setKeyword2_value(sendTemplate.getKeyword2_value());
				entity.setKeyword3_color(template.getKeyword3_color());
				entity.setKeyword3_value(sendTemplate.getKeyword3_value());
				entity.setKeyword4_color(template.getKeyword4_color());
				entity.setKeyword4_value(sendTemplate.getKeyword4_value());
				entity.setKeyword5_color(template.getKeyword5_color());
				entity.setKeyword5_value(sendTemplate.getKeyword5_value());
				entity.setRemark_color(template.getRemark_color());
				entity.setRemark_value(sendTemplate.getRemark_value());
				//**************set new field************************************
				Map<String, Method> map = new HashMap<String, Method>();
				Method[] arr = TemplateRequestEntity.class.getDeclaredMethods();
				for (Method m : arr) {
					String name = m.getName();
					if (name.startsWith("set") && (name.endsWith("_value") || name.endsWith("_color"))) {
						name = name.substring(3, name.length());
						map.put(name.toLowerCase(), m);
					}
				}
				if (StringHelper.isNotEmpty(template.getKeyword1_name())) {
					Method vMethod = map.get(template.getKeyword1_name() + "_value");
					if (vMethod != null) {
						try {
							vMethod.invoke(entity, new Object[] {sendTemplate.getKeyword1_value()});
						} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
							e.printStackTrace();
						}
					}
				}
				
				if (StringHelper.isNotEmpty(template.getKeyword2_name())) {
					Method vMethod = map.get(template.getKeyword2_name() + "_value");
					if (vMethod != null) {
						try {
							vMethod.invoke(entity, new Object[] {sendTemplate.getKeyword2_value()});
						} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
							e.printStackTrace();
						}
					}
				}
				
				if (StringHelper.isNotEmpty(template.getKeyword3_name())) {
					Method vMethod = map.get(template.getKeyword3_name() + "_value");
					if (vMethod != null) {
						try {
							vMethod.invoke(entity, new Object[] {sendTemplate.getKeyword3_value()});
						} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
							e.printStackTrace();
						}
					}
				}
				
				if (StringHelper.isNotEmpty(template.getKeyword4_name())) {
					Method vMethod = map.get(template.getKeyword4_name() + "_value");
					if (vMethod != null) {
						try {
							vMethod.invoke(entity, new Object[] {sendTemplate.getKeyword4_value()});
						} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
							e.printStackTrace();
						}
					}
				}
				
				if (StringHelper.isNotEmpty(template.getKeyword5_name())) {
					Method vMethod = map.get(template.getKeyword5_name() + "_value");
					if (vMethod != null) {
						try {
							vMethod.invoke(entity, new Object[] {sendTemplate.getKeyword5_value()});
						} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
							e.printStackTrace();
						}
					}
				}
				//send
				WxTemplateLog log = new WxTemplateLog();
				log.setBusiness_type(business_type);
				log.setOpen_id(open_id);
				log.setWx_id(WeiXinUtil.getWxDefine(app_id).getWx_id());
				log.setTemplate_code(template.getTemplate_code());
				sendWeiXinTemplate(app_id, entity, log, thread_flag);
			}

		}
	}

	public static void sendWeiXinTemplate(String app_id, WxTemplate template, String open_id, boolean thread_flag) {
		TemplateRequestEntity entity = new TemplateRequestEntity(template.getTemplate_code(), open_id,
				template.getContent_value(), template.getKeyword1_value());
		entity.setUrl(template.getTemplate_url());
		entity.setTopcolor(template.getTop_color());
		entity.setFirst_color(template.getContent_color());
		entity.setKeyword1_color(template.getKeyword1_color());
		entity.setKeyword1_value(template.getKeyword1_value());
		entity.setKeyword2_color(template.getKeyword2_color());
		entity.setKeyword2_value(template.getKeyword2_value());
		entity.setKeyword3_color(template.getKeyword3_color());
		entity.setKeyword3_value(template.getKeyword3_value());
		entity.setKeyword4_color(template.getKeyword4_color());
		entity.setKeyword4_value(template.getKeyword4_value());
		entity.setKeyword5_color(template.getKeyword5_color());
		entity.setKeyword5_value(template.getKeyword5_value());
		entity.setRemark_color(template.getRemark_color());
		entity.setRemark_value(template.getRemark_value());

		WxTemplateLog log = new WxTemplateLog();
		log.setBusiness_type("Custom");
		log.setOpen_id(open_id);
		log.setWx_id(WeiXinUtil.getWxDefine(app_id).getWx_id());
		log.setTemplate_code(template.getTemplate_code());
		sendWeiXinTemplate(app_id, entity, log, thread_flag);
	}
	//新的发送消息--
	public static void sendWeiXinTemplateSpecial(String app_id, WxTemplate template, String open_id, boolean thread_flag) {
		TemplateRequestEntity entity = new TemplateRequestEntity(template.getTemplate_code(), open_id,
				template.getContent_value(), template.getKeyword1_value());
		entity.setUrl(template.getTemplate_url());
		entity.setTopcolor(template.getTop_color());
		entity.setRemark_color(template.getRemark_color());
		entity.setRemark_value(template.getRemark_value());
		
		Map<String, Method> map = new HashMap<String, Method>();
		Method[] arr = TemplateRequestEntity.class.getDeclaredMethods();
		for (Method m : arr) {
			String name = m.getName();
			if (name.startsWith("set") && (name.endsWith("_value") || name.endsWith("_color"))) {
				name = name.substring(3, name.length());
				map.put(name.toLowerCase(), m);
			}
		}
		
		if (StringHelper.isNotEmpty(template.getKeyword1_name())) {
			Method vMethod = map.get(template.getKeyword1_name() + "_value");
			Method cMethod = map.get(template.getKeyword1_name() + "_color");
			if (vMethod != null) {
				try {
					vMethod.invoke(entity, new Object[] {template.getKeyword1_value()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
			if (cMethod != null) {
				try {
					cMethod.invoke(entity, new Object[] {template.getKeyword1_color()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		
		if (StringHelper.isNotEmpty(template.getKeyword2_name())) {
			Method vMethod = map.get(template.getKeyword2_name() + "_value");
			Method cMethod = map.get(template.getKeyword2_name() + "_color");
			if (vMethod != null) {
				try {
					vMethod.invoke(entity, new Object[] {template.getKeyword2_value()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
			if (cMethod != null) {
				try {
					cMethod.invoke(entity, new Object[] {template.getKeyword2_color()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		
		if (StringHelper.isNotEmpty(template.getKeyword3_name())) {
			Method vMethod = map.get(template.getKeyword3_name() + "_value");
			Method cMethod = map.get(template.getKeyword3_name() + "_color");
			if (vMethod != null) {
				try {
					vMethod.invoke(entity, new Object[] {template.getKeyword3_value()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
			if (cMethod != null) {
				try {
					cMethod.invoke(entity, new Object[] {template.getKeyword3_color()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		
		if (StringHelper.isNotEmpty(template.getKeyword4_name())) {
			Method vMethod = map.get(template.getKeyword4_name() + "_value");
			Method cMethod = map.get(template.getKeyword4_name() + "_color");
			if (vMethod != null) {
				try {
					vMethod.invoke(entity, new Object[] {template.getKeyword4_value()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
			if (cMethod != null) {
				try {
					cMethod.invoke(entity, new Object[] {template.getKeyword4_color()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		
		if (StringHelper.isNotEmpty(template.getKeyword5_name())) {
			Method vMethod = map.get(template.getKeyword5_name() + "_value");
			Method cMethod = map.get(template.getKeyword5_name() + "_color");
			if (vMethod != null) {
				try {
					vMethod.invoke(entity, new Object[] {template.getKeyword5_value()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
			if (cMethod != null) {
				try {
					cMethod.invoke(entity, new Object[] {template.getKeyword5_color()});
				} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					e.printStackTrace();
				}
			}
		}
		
		WxTemplateLog log = new WxTemplateLog();
		log.setBusiness_type("Custom");
		log.setOpen_id(open_id);
		log.setWx_id(WeiXinUtil.getWxDefine(app_id).getWx_id());
		log.setTemplate_code(template.getTemplate_code());
		//LogHelper.info("x.消息发送template--->" + JsonHelper.fromObject(template));
		//LogHelper.info("y.消息发送entity--->" + JsonHelper.fromObject(entity));
		sendWeiXinTemplateSpecial(app_id, entity, log, thread_flag);
	}
	
	public static String replaceValues(Map<String, Object> valueMap, String source) {
		if(source == null)
			return null;
		if(StringHelper.isEmpty(source))
			return "";
		for (String key : valueMap.keySet()) {
			if (valueMap.get(key) == null)
				continue;
			source = source.replaceAll("@\\{" + key + "\\}", valueMap.get(key).toString());
		}
		return source;

	}
	

	public static String replaceValues(Map<String, String> paramMap, Map<String, Object> valueMap, String source) {
		if (paramMap == null)
			return source;
		for (String key : paramMap.keySet()) {
			if (!valueMap.containsKey(key))
				continue;
			if (valueMap.get(key) == null)
				continue;
			source = source.replaceAll("@\\{" + key + "\\}", valueMap.get(key).toString());
		}
		return source;

	}

	/********************************
	 * 发送模版消息
	 * 
	 * @param wx_id
	 *            微信公众号内部编号
	 * @param entity
	 *            模版消息
	 * @param run_thread
	 *            是否线程模式发送
	 */
	public static WxResponseJson sendWeiXinTemplate(String app_id, TemplateRequestEntity entity,
			final WxTemplateLog log, boolean run_thread) {
		final TemplateSendRequestJson json = entity.getRequestJson();
		final TemplateSendRequest rq = new TemplateSendRequest(json);
		try {
			log.setTemplate_msg(JsonHelper.fromObject(json));
		} catch (Exception e) {

		}
		rq.setWxDefine(app_id);
		if (run_thread) {
			new Thread(new Runnable() {
				public void run() {
					sendWeiXinTemplate(rq, log);
				}
			}).start();
		} else
			sendWeiXinTemplate(rq, log);
		return null;
	}
	
	public static WxResponseJson sendWeiXinTemplateSpecial(String app_id, TemplateRequestEntity entity,
			final WxTemplateLog log, boolean run_thread) {
		final TemplateSendRequestJson json = entity.getRequestJson();
		final TemplateSendRequest rq = new TemplateSendRequest(json);
		try {
			log.setTemplate_msg(JsonHelper.fromObject(json));
		} catch (Exception e) {

		}
		rq.setWxDefine(app_id);
		if (run_thread) {
			new Thread(new Runnable() {
				public void run() {
					sendWeiXinTemplateSpecial(rq, log);
				}
			}).start();
		} else
			sendWeiXinTemplateSpecial(rq, log);
		return null;
	}
	
	private static WxResponseJson sendWeiXinTemplateSpecial(TemplateSendRequest rq, WxTemplateLog log) {
		WxResponseJson json = null;
		try {
			json = rq.request();
		} catch (Exception e) {
			if (log != null) {
				log.setResult_status("error");
				log.setResult_msg(e.getMessage().length() > 128 ? e.getMessage().substring(0, 128) : e.getMessage());
				SpringHelper.getBean(WxTemplateLogDao.class).logTemplate(log);
			}
			return null;
		}
		if (log != null) {
			if (json != null) {
				log.setResult_status(json.getErrcode() + "");
				log.setResult_msg(json.getErrmsg());
				LogHelper.info("消息发送--->" + json.getErrmsg());
			} else {
				log.setResult_status("error");
				log.setResult_msg("未知错误");
			}
			SpringHelper.getBean(WxTemplateLogDao.class).logTemplate(log);
		}
		// 保存
		return json;
	}

	private static WxResponseJson sendWeiXinTemplate(TemplateSendRequest rq, WxTemplateLog log) {
		WxResponseJson json = null;
		try {
			json = rq.request();
		} catch (Exception e) {
			if (log != null) {
				log.setResult_status("error");
				log.setResult_msg(e.getMessage().length() > 128 ? e.getMessage().substring(0, 128) : e.getMessage());
				SpringHelper.getBean(WxTemplateLogDao.class).logTemplate(log);
			}
			return null;
		}
		if (log != null) {
			if (json != null) {
				log.setResult_status(json.getErrcode() + "");
				log.setResult_msg(json.getErrmsg());
			} else {
				log.setResult_status("error");
				log.setResult_msg("未知错误");
			}
			SpringHelper.getBean(WxTemplateLogDao.class).logTemplate(log);
		}
		// 保存
		return json;
	}

	/********************************
	 * 发送模版消息
	 * 
	 * @param wx_id
	 *            微信公众号内部编号
	 * @param entity
	 *            模版消息
	 */
	public static WxResponseJson sendWeiXinTemplate(String app_id, TemplateRequestEntity entity, WxTemplateLog log) {
		return sendWeiXinTemplate(app_id, entity, log, false);
	}

}
