package com.uas.search.console.b2b.jms;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import com.uas.search.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.uas.search.b2b.exception.SearchException;
import com.uas.search.b2b.service.SearchService.Table_name;
import com.uas.search.console.b2b.model.ParsedQueueMessage;
import com.uas.search.console.b2b.util.ClassAndTableNameUtils;
import com.uas.search.console.b2b.util.JSONUtils;

/**
 * 对得到的队列消息进行解析的工具
 * 
 * @author sunyj
 * @param <T>
 * @since 2016年11月9日 上午11:30:02
 */
@Service
public class QueueMessageParser {

	/**
	 * 对得到的json消息进行解析
	 * 
	 * @param message
	 *            消息队列里的消息
	 * @return ParsedQueueMessage对象
	 * @throws JSONException
	 */
	// {"method":"value1","table":"value2","ids":"[1,2,3]"}
	// {"method":"value1","table":"value2","data":[{"pr_id":1,"pr_code":"ff"},{...}]}
	public ParsedQueueMessage parse(String message) throws JSONException {
		if (StringUtils.isEmpty(message) || message.equals("{}")) {
			return null;
		}
		JSONObject jsonObject = JSONUtils.parseObject(message);
		if (!jsonObject.containsKey("method") || !jsonObject.containsKey("table")) {
			return null;
		}

		// ids或data必须有一个存在
		if (!jsonObject.containsKey("ids") && !jsonObject.containsKey("data")) {
			return null;
		}

		ParsedQueueMessage parsedQueueMessage = new ParsedQueueMessage();
		// 解析数据库表的更改类型
		String method = jsonObject.getString("method");
		if (method.equalsIgnoreCase("insert")) {
			parsedQueueMessage.setMethodType(ParsedQueueMessage.INSERT);
		}

		else if (method.equalsIgnoreCase("update")) {
			parsedQueueMessage.setMethodType(ParsedQueueMessage.UPDATE);
		}

		else if (method.equalsIgnoreCase("delete")) {
			parsedQueueMessage.setMethodType(ParsedQueueMessage.DELETE);
		} else {
			return null;
		}

		// 解析哪个表有更改
		String table = jsonObject.getString("table");
		Class<?> clazz = ClassAndTableNameUtils.toClass(Table_name.valueOf(table.toUpperCase()));
		Object[] objects = null;
		if (jsonObject.containsKey("ids")) {
			objects = parseToListByIds(jsonObject, clazz).toArray();
		} else {
			objects = parseToListByData(jsonObject, clazz).toArray();
		}

		parsedQueueMessage.setObjects(objects);
		return parsedQueueMessage;
	}

	/**
	 * 根据消息队列的消息解析对象
	 * 
	 * @param <T>
	 * 
	 * @param jsonObject
	 *            消息转为的json对象
	 * @param clazz
	 *            实体类型
	 * @return 实体对象列表
	 */
	private <T> List<T> parseToListByData(JSONObject jsonObject, Class<T> clazz) {
		List<T> list = new ArrayList<>();
		JSONArray jsonArray = JSONObject.parseArray(jsonObject.getString("data"));
		if (jsonArray == null || jsonArray.isEmpty()) {
			return list;
		}
		for (Object obj : jsonArray) {
			T object = JSONObject.parseObject(obj.toString(), clazz);
			list.add(object);
		}
		return list;
	}

	/**
	 * 根据消息队列的消息解析对象
	 * 
	 * @param <T>
	 * 
	 * @param jsonObject
	 *            消息转为的json对象
	 * @param clazz
	 *            实体类型
	 * @return 实体对象列表
	 */
	private <T> List<T> parseToListByIds(JSONObject jsonObject, Class<T> clazz) {
		// 获取实体的dao
		JpaRepository<T, Long> dao = ClassAndTableNameUtils.getDao(clazz);
		Set<Long> ids = getIds(jsonObject.getJSONArray("ids"));
		List<T> list = new ArrayList<>();
		// delete操作
		// 删除后数据库中可能已经没有相应数据了，无法通过dao获取，需要手动创建对象
		if (jsonObject.getString("method").equalsIgnoreCase("delete")) {
			for (Long id : ids) {
				list.add(ClassAndTableNameUtils.createObject(clazz, id));
			}
		} else {
			try {
				list = dao.findAll(ids);
			} catch (Throwable e) {
				// 防止SQLRecoverableException导致应用终止
				throw new SearchException(e).setDetailedMessage(e);
			}
		}

		return list;
	}

	/**
	 * 从队列消息中获取id（同时消除重复id）
	 * 
	 * @param jsonArray
	 *            队列消息中json格式的id
	 * @return
	 */
	private Set<Long> getIds(JSONArray jsonArray) {
		if (jsonArray == null || jsonArray.isEmpty()) {
			return null;
		}
		Object[] ids = jsonArray.toArray();
		Set<Long> idsSet = new HashSet<>();
		for (int i = 0; i < ids.length; i++) {
			idsSet.add(Long.parseLong(ids[i].toString()));
		}
		return idsSet;
	}

}
