package com.pcloud.common.utils;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.pcloud.common.dto.ResponseDto;
import com.pcloud.common.exceptions.BizException;

/**
 * Created by zengqiang on 17-12-14.
 */
public class ResponseHandleUtil {

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

	/**
	 * 解析一层list包装泛型数据
	 * 
	 * @param obj
	 *            需要解析的数据对象
	 * @param clazz
	 *            list内元素类型
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> getListData(Object obj, Class<T> clazz) {
		if (null == obj) {
			return null;
		}
		return JSON.parseArray(JSON.toJSONString(obj), clazz);
	}

	public static <K, V> Map<K, V> getMapData(Object obj, Class<K> clazzK, Class<V> clazzV) {
		if (null == obj) {
			return null;
		}
		JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(obj));
		Map<K, V> resultMap = Maps.newHashMap();
		for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
			resultMap.put(JSON.parseObject(JSON.toJSONString(entry.getKey()), clazzK),
					JSON.parseObject(JSON.toJSONString(entry.getValue()), clazzV));
		}
		return resultMap;
	}

    /**
     * 解析map的value是list的泛型数据
     * @param obj 需要解析的数据对象
     * @param clazzK key元素类型
     * @param clazzT value中list元素类型
     * @return
     */
	public static <K, T> Map<K, List<T>> getMapListData(Object obj, Class<K> clazzK, Class<T> clazzT) {
		if (null == obj) {
			return null;
		}
		JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(obj));
		Map<K, List<T>> resultMap = Maps.newHashMap();
		for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
			resultMap.put(JSON.parseObject(JSON.toJSONString(entry.getKey()), clazzK),
                    JSON.parseArray(JSON.toJSONString(entry.getValue()), clazzT));
		}
		return resultMap;
	}

	public static <T> T parseResponse(ResponseEntity<?> entity, Class<T> clazz) {
		Object obj = parseResponse(entity);
		if (null == obj) {
			return null;
		}
		if (clazz.equals(Long.class)) {
			if (obj instanceof Long) {
				return clazz.cast(obj);
			} else if (obj instanceof Number) {
				return clazz.cast(((Number) obj).longValue());
			}
		} else if (clazz.equals(Integer.class)) {
			if (obj instanceof Integer) {
				return clazz.cast(obj);
			} else if (obj instanceof Number) {
				return clazz.cast(((Number) obj).intValue());
			}
		} else if (clazz.equals(Double.class)) {
			if (obj instanceof Double) {
				return clazz.cast(obj);
			} else if (obj instanceof Number) {
				return clazz.cast(((Number) obj).doubleValue());
			}
		} else if (clazz.equals(Float.class)) {
			if (obj instanceof Float) {
				return clazz.cast(obj);
			} else if (obj instanceof Number) {
				return clazz.cast(((Number) obj).floatValue());
			}
		} else if (clazz.equals(BigDecimal.class)) {
			if (obj instanceof BigDecimal) {
				return clazz.cast(obj);
			} else if (obj instanceof Number) {
				return clazz.cast(BigDecimal.valueOf(((Number) obj).doubleValue()));
			}
		}
		try {
			return clazz.cast(obj);
		} catch (ClassCastException e) {
			return JSON.parseObject(JSON.toJSONString(obj), clazz);
		}
	}

	/**
	 * List数据解析
	 * 
	 * @param entity
	 * @param clazz
	 * @param <T>
	 *            List元素类型
	 * @return
	 */
	public static <T> List<T> parseListResponse(ResponseEntity<?> entity, Class<T> clazz) {
		List list = parseResponse(entity, List.class);
		if (null == list) {
			return list;
		}

		return JSON.parseArray(JSON.toJSONString(list), clazz);
	}

	/**
	 *
	 * @param entity
	 * @param clazzK
	 *            key class类型
	 * @param clazzV
	 *            value class类型
	 * @param <K>
	 * @param <V>
	 * @return
	 */
	public static <K, V> Map<K, V> parseMapResponse(ResponseEntity<?> entity, Class<K> clazzK, Class<V> clazzV) {
		Map map = parseResponse(entity, Map.class);
		if (null == map) {
			return map;
		}

		Map<K, V> result = new HashMap<>();
		for (Object o : map.entrySet()) {
			Map.Entry entry = (Map.Entry) o;
			K k = JSON.parseObject(JSON.toJSONString(entry.getKey()), clazzK);
			V v = JSON.parseObject(JSON.toJSONString(entry.getValue()), clazzV);
			result.put(k, v);
		}
		return result;
	}

	/**
	 * list转换
	 * 
	 * @param entity
	 * @param clazz
	 * @return
	 */
	public static <T> List<T> parseList(ResponseEntity<?> entity, Class<T> clazz) {
		Object object = parseResponse(entity);
		if (object == null) {
			return null;
		}
		return JSONArray.parseArray(JSON.toJSONString(object), clazz);
	}

	/**
	 * Map转换
	 * 
	 * @param entity
	 * @param clazzK
	 * @param clazzV
	 * @return
	 */
	public static <K, V> Map<K, V> parseMap(ResponseEntity<?> entity, Class<K> clazzK, Class<V> clazzV) {
		Object object = parseResponse(entity, Map.class);
		if (object == null) {
			return null;
		}
		return getMapData(object, clazzK, clazzV);
	}

    /**
     * Map List转换
     * @param entity 需要解析的数据对象
     * @param clazzK key元素类型
     * @param clazzT value中list元素类型
     * @return
     */
    public static <K, T> Map<K, List<T>> parseMapList(ResponseEntity<?> entity, Class<K> clazzK, Class<T> clazzT) {
        Object object = parseResponse(entity, Map.class);
        if (object == null) {
            return null;
        }
        return getMapListData(object, clazzK, clazzT);
    }

	public static Object parseResponse(ResponseEntity<?> entity) {
		if (null == entity) {
			LOGGER.warn("null response object");
			return null;
		}
		int statusCode = entity.getStatusCodeValue();
		Object errMsg = entity.getBody();
		if (statusCode == 500) {
			LOGGER.error("【内部调用异常】异常信息: " + errMsg);
			throw new RuntimeException("【内部调用异常】异常信息: " + errMsg);
		} else if (statusCode == 400) {
			LOGGER.warn("【请求异常】异常信息: " + errMsg);
			throw new RuntimeException("【请求异常】异常信息: " + errMsg);
		} else if (statusCode != 200) {
			LOGGER.warn("【请求错误】错误信息: " + errMsg);
			throw new RuntimeException("【请求错误】错误信息: " + errMsg);
		}
		ResponseDto<?> body = (ResponseDto<?>) entity.getBody();
		if (body == null) {
			LOGGER.warn("【请求NULL】ResponseDto==null");
			return null;
		}
		if (body.getErrCode() != 0) {
			LOGGER.warn("【业务异常】:" + body.getErrCode() + ", 异常信息: " + body.getMessage());
			throw new BizException(body.getErrCode(), body.getMessage());
		}
		return body.getData();
	}

	public static <T> ResponseEntity<ResponseDto<T>> toResponse(T data) {
		if (null == data) {
			LOGGER.warn("null data object");
			return null;
		}
		ResponseDto<T> body = new ResponseDto<>(data);
		return new ResponseEntity<ResponseDto<T>>(body, HttpStatus.OK);
	}

}