package cn.hmsoft.helper;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

import cn.hmsoft.frame.exception.BusinessException;

/******************************
 * @note 数组辅助工具
 * @author revisit@126.com
 * @Company: www.hmsoft.cn
 * @create 2017-05-04 22:40:14
 * @version 4.0.0
 */
public abstract class CollectionHelper {

	/************************************************
	 * 判断数组是否为空，及没有任何记录
	 */
	public final static boolean isEmpty(Collection<?> list) {
		if (list == null || list.size() == 0)
			return true;
		return false;
	}

	/***************************************************
	 * 判断数组是否不为空，至少有一条记录
	 */
	public final static boolean isNotEmpty(Collection<?> list) {
		return !isEmpty(list);
	}

	/***************************************************
	 * 判断数组是否有且只有一条记录
	 */
	public final static boolean hasOneValue(Collection<?> list) {
		return list != null && list.size() == 1;
	}

	/*************************
	 * 拼接字符串
	 */
	public static String join(String[] array, String joinString) {
		if (array == null || array.length == 0)
			return "";
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < array.length - 1; i++)
			sb.append(array[i] == null ? "" : array[i] + joinString);
		sb.append(array[array.length - 1]);
		return sb.toString();
	}

	/*************************
	 * 拼接字符串
	 */
	public static String join(Object[] array, String joinString) {
		if (array == null || array.length == 0)
			return "";
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < array.length - 1; i++)
			sb.append(array[i] == null ? "" : array[i].toString() + joinString);
		sb.append(array[array.length - 1].toString());
		return sb.toString();
	}

	/****************************************
	 * 将List对象中某个属性的值进行拼接
	 */
	public static String join(List<?> list, String fieldName, String joinString) {
		if (isEmpty(list))
			return "";
		StringBuilder sb = new StringBuilder();
		try {
			Field field = list.get(0).getClass().getDeclaredField(fieldName);
			field.setAccessible(true);
			for (int i = 0; i < list.size() - 1; i++) {
				Object value = field.get(list.get(i));
				sb.append(value == null ? "" : value.toString() + joinString);
			}
			sb.append(field.get(list.get(list.size() - 1)).toString());
		} catch (Exception e) {
		}
		return sb.toString();
	}

	/***************************************
	 * 数组中随机获取一个元素，然后移除该元素，使用ThreadLocalRandom以提高性能，需要JDK1.7
	 */
	public static <T> T randomValue(List<T> list) {
		int index = ThreadLocalRandom.current().nextInt(list.size());
		T entity = list.get(index);
		list.remove(index);
		return entity;
	}

	/********************************************
	 * 将数组填充到指定长度
	 */

	public static void padSize(Collection<?> array, int size) {
		int k = size - array.size();
		for (int i = 1; i <= k; i++)
			array.add(null);
	}

	/********************************************
	 * 将数组填充到指定长度
	 */
	public static void padSize(Map<String, List<?>> map, int size) {
		for (String key : map.keySet()) {
			List<?> array = map.get(key);
			padSize(array, size);
		}

	}

	/*******************************
	 * 从map中获取数据
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getParamValue(Map<?, ?> paramMap, String param_name, T default_value) {
		if (!paramMap.containsKey(param_name))
			return default_value;
		try {
			return (T) paramMap.get(param_name);
		} catch (Exception e) {
			return default_value;
		}
	}

	/**********************
	 * 复制数组，如果length为负数，反向复制
	 * 
	 * @param array
	 * @param start
	 * @param length
	 * @return
	 */
	public static Object[] subArray(Object[] array, int start, int length) {
		if (array == null || array.length < start + length)
			return new Object[0];
		Object[] list = new Object[length];
		int step = length;
		if (step < 0)
			step = 0 - step;
		for (int i = 0; i < step; i++)
			list[i] = array[start + i];
		return list;
	}

	/*******************
	 * 数组交换两个项目位置
	 */
	public static <T> void swap(T[] a, int i, int j) {
		T temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

	/**************************
	 * 数组随机排序
	 */
	public static <T> void shuffle(T[] arr) {
		Random rand = new Random();
		int length = arr.length;
		for (int i = length; i > 0; i--) {
			int randInd = rand.nextInt(i);
			swap(arr, randInd, i - 1);
		}
	}

	/********************
	 * 将数转换成Map
	 * 
	 * @param clazz
	 *            key 数据类型
	 * @param field_name
	 *            从哪个属性作为key值
	 * @param array
	 *            数组
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T, V> Map<T, V> toMap(Class<T> clazz, String field_name, List<V> array) {
		Map<T, V> map = new LinkedHashMap<T, V>();
		if (array != null) {
			Field field = null;
			for (V v : array) {
				if (field == null) {
					try {
						field = v.getClass().getDeclaredField(field_name);
						field.setAccessible(true);
					} catch (Exception e) {
						throw new BusinessException(
								"can not find filed [" + field_name + "] in class:[" + v.getClass().getName() + "]");
					}
				}
				T obj = null;
				try {
					obj = (T) field.get(v);
				} catch (Exception e) {
					throw new BusinessException(
							"can not find get [" + field_name + "] value in class:[" + v.getClass().getName() + "]");
				}
				if (obj != null)
					map.put(obj, v);
			}
		}
		return map;
	}
}
