package com.uas.report.util;

import com.alibaba.fastjson.JSONArray;
import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
import java.util.Map.Entry;

/**
 * 对象工具类
 *
 * @author sunyj
 * @since 2017年9月1日 下午3:54:26
 */
public class ObjectUtils {

	/**
	 * 判断是否为 null、空数组、空串或者空集合
	 *
	 * @param obj
	 *            对象
	 * @return 是否为 null、空数组、空串或者空集合
	 */
	public static boolean isEmpty(Object obj) {
		if (obj == null) {
			return true;
		}
		if (obj.getClass().isArray()) {
			if (obj instanceof long[]) {
				return ArrayUtils.isEmpty((long[]) obj);
			} else if (obj instanceof int[]) {
				return ArrayUtils.isEmpty((int[]) obj);
			} else if (obj instanceof short[]) {
				return ArrayUtils.isEmpty((short[]) obj);
			} else if (obj instanceof byte[]) {
				return ArrayUtils.isEmpty((byte[]) obj);
			} else if (obj instanceof char[]) {
				return ArrayUtils.isEmpty((char[]) obj);
			} else if (obj instanceof boolean[]) {
				return ArrayUtils.isEmpty((boolean[]) obj);
			} else if (obj instanceof float[]) {
				return ArrayUtils.isEmpty((float[]) obj);
			} else if (obj instanceof double[]) {
				return ArrayUtils.isEmpty((double[]) obj);
			}
			return ArrayUtils.isEmpty((Object[]) obj);
		}
		return (obj instanceof String && StringUtils.isEmpty(obj))
				|| (obj instanceof Collection && CollectionUtils.isEmpty((Collection<?>) obj))
				|| (obj instanceof Map && CollectionUtils.isEmpty((Map<?, ?>) obj));
	}

	/**
	 * 将对象转为 String
	 *
	 * @param obj
	 *            对象
	 * @return 转换的 String
	 */
	public static String toString(Object obj) {
		if (obj == null) {
			return "";
		}
		if (obj instanceof String) {
			return (String) obj;
		}
		if (obj.getClass().isArray()) {
			if (obj instanceof long[]) {
				return Arrays.toString((long[]) obj);
			} else if (obj instanceof int[]) {
				return Arrays.toString((int[]) obj);
			} else if (obj instanceof short[]) {
				return Arrays.toString((short[]) obj);
			} else if (obj instanceof byte[]) {
				return Arrays.toString((byte[]) obj);
			} else if (obj instanceof char[]) {
				return Arrays.toString((char[]) obj);
			} else if (obj instanceof boolean[]) {
				return Arrays.toString((boolean[]) obj);
			} else if (obj instanceof float[]) {
				return Arrays.toString((float[]) obj);
			} else if (obj instanceof double[]) {
				return Arrays.toString((double[]) obj);
			}
			return Arrays.toString((Object[]) obj);
		}
		return obj.toString();
	}

	/**
	 * 深克隆对象
	 *
	 * @param t
	 *            要克隆的对象
	 * @return 克隆得到的对象
	 */
	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T clone(T t)
			throws IOException, ClassNotFoundException, NotSerializableException {
		if (t == null) {
			return null;
		}
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		new ObjectOutputStream(out).writeObject(t);
		ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
		return (T) in.readObject();
	}

	/**
	 * 深克隆集合对象
	 *
	 * @param collection
	 *            要克隆的对象
	 * @return 克隆得到的对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> Collection<T> clone(Collection<T> collection) throws InstantiationException,
			IllegalAccessException, NotSerializableException, ClassNotFoundException, IOException {
		if (collection == null) {
			return null;
		}
		Collection<T> result = collection.getClass().newInstance();
		for (T t : collection) {
			if (t instanceof Serializable) {
				result.add((T) clone((Serializable) t));
			} else if (t instanceof Collection) {
				result.add((T) clone((Collection<?>) t));
			} else if (t instanceof Map) {
				result.add((T) clone((Map<String, ?>) t));
			} else {
				throw new IllegalArgumentException("未实现 Serializable 接口");
			}
		}
		return result;
	}

	/**
	 * 深克隆 Map 对象
	 *
	 * @param map
	 *            要克隆的对象
	 * @return 克隆得到的对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> Map<String, T> clone(Map<String, T> map) throws InstantiationException, IllegalAccessException,
			NotSerializableException, ClassNotFoundException, IOException {
		if (map == null) {
			return null;
		}
		Map<String, T> result = map.getClass().newInstance();
		Set<Entry<String, T>> entrySet = map.entrySet();
		for (Entry<String, T> entry : entrySet) {
			T value = entry.getValue();
			if (value instanceof Serializable) {
				result.put(entry.getKey(), (T) clone((Serializable) value));
			} else if (value instanceof Collection) {
				result.put(entry.getKey(), (T) clone((Collection<?>) value));
			} else if (value instanceof Map) {
				result.put(entry.getKey(), (T) clone((Map<String, ?>) value));
			} else {
				throw new IllegalArgumentException("未实现 Serializable 接口");
			}
		}
		return result;
	}

	/**
	 * JSONArray 转为指定类型的 List
	 *
	 * @param array
	 *            JSONArray
	 * @param clazz
	 *            指定的类型
	 * @param <T>
	 *            指定的类型
	 * @return 指定类型的 List
	 */
	public static <T> List<T> toList(JSONArray array, Class<T> clazz) {
		if (array == null) {
			return null;
		}
		List<T> list = new ArrayList<>();
		for (int i = 0; i < array.size(); i++) {
			list.add(array.getObject(i, clazz));
		}
		return list;
	}

	/**
	 * 利用反射获取指定对象的指定字段的值
	 *
	 * @param field
	 *            指定字段
	 * @param k
	 *            指定对象
	 * @return 指定字段的值
	 */
	public static <K> Object getValue(Field field, K k) throws IllegalStateException {
		Object value;
		try {
			if (!field.isAccessible()) {
				field.setAccessible(true);
				value = field.get(k);
				field.setAccessible(false);
			} else {
				value = field.get(k);
			}
		} catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
			throw new IllegalStateException("通过反射取值失败", e);
		}
		return value;
	}

	/**
	 * 利用反射递归获取指定对象的指定字段的值
	 *
	 * @param field
	 *            指定字段
	 * @param k
	 *            指定对象
	 * @return 指定字段的值
	 */
	public static <K> Object recursivelyGetValue(String field, K k) {
		return getValue(recursivelyGetField(field, k.getClass()), k);
	}

	/**
	 * 递归获取指定类的指定字段（包括父类的私有字段）
	 *
	 * @param field
	 *            指定字段
	 * @param clazz
	 *            指定类
	 * @return 指定字段
	 * @throws IllegalArgumentException
	 */
	public static Field recursivelyGetField(String field, Class<?> clazz) throws IllegalArgumentException {
		try {
			return clazz.getDeclaredField(field);
		} catch (NoSuchFieldException e) {
			Class<?> superclass = clazz.getSuperclass();
			if (superclass != null) {
				return recursivelyGetField(field, superclass);
			}
			throw new IllegalArgumentException(clazz + "中不存在字段：" + field);
		}
	}

	/**
	 * 获取指定类的指定字段
	 *
	 * @param field
	 *            指定字段
	 * @param clazz
	 *            指定类
	 * @return 指定字段
	 * @throws IllegalArgumentException
	 */
	public static Field getField(String field, Class<?> clazz) throws IllegalArgumentException {
		try {
			return clazz.getDeclaredField(field);
		} catch (NoSuchFieldException e) {
			throw new IllegalArgumentException(clazz + "中不存在字段：" + field);
		}
	}

	/**
	 * 递归获取父类（包括私有字段）的所有字段
	 *
	 * @param clazz
	 *            指定类
	 * @return 所有字段
	 */
	public static List<Field> recursivelyGetParentField(Class<?> clazz) {
		List<Field> fields = new ArrayList<>();
		Class<?> superclass = clazz.getSuperclass();
		if (superclass != null) {
			fields.addAll(recursivelyGetField(superclass));
		}
		return fields;
	}

	/**
	 * 递归获取所有字段（包括父类的私有字段）
	 *
	 * @param clazz
	 *            指定类
	 * @return 所有字段
	 */
	private static List<Field> recursivelyGetField(Class<?> clazz) {
		List<Field> fields = new ArrayList<>();
		Field[] declaredFields = clazz.getDeclaredFields();
		if (!ArrayUtils.isEmpty(declaredFields)) {
			fields.addAll(Arrays.asList(declaredFields));
		}
		Class<?> superclass = clazz.getSuperclass();
		if (superclass != null) {
			fields.addAll(recursivelyGetField(superclass));
		}
		return fields;
	}
}
