package com.prolog.cs.biz.inbound.utils;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class ObjectUtils {
	/**
	 * 判断参数的格式是否为“yyyyMMdd”格式的合法日期字符串
	 * 
	 * @author Liang.Wang
	 * @since 02/24/15
	 * @param str
	 * @return true/false
	 */
	public static boolean isValidDate(String str) {
		try {
			if (str != null && !str.equals("")) {
				if (str.length() == 8 || str.length() == 6) {
					// 闰年标志
					boolean isLeapYear = false;
					String year = str.substring(0, 4);
					String month = str.substring(4, 6);
					String day = null;
					if (str.length() == 8) {
						day = str.substring(6, 8);
					}

					int vYear = Integer.parseInt(year);
					// 判断年份是否合法
					if (vYear < 1900 || vYear > 2200) {
						return false;
					}
					// 判断是否为闰年
					if (vYear % 4 == 0 && vYear % 100 != 0 || vYear % 400 == 0) {
						isLeapYear = true;
					}
					// 判断月份
					// 1.判断月份
					if (month.startsWith("0")) {
						String units4Month = month.substring(1, 2);
						int vUnits4Month = Integer.parseInt(units4Month);
						if (vUnits4Month == 0) {
							return false;
						}
						if (vUnits4Month == 2) {
							// 获取2月的天数
							if (day != null && !str.equals("")) {
								int vDays4February = Integer.parseInt(day);
								if (isLeapYear) {
									if (vDays4February > 29)
										return false;
								} else {
									if (vDays4February > 28)
										return false;
								}
							}
						}
					} else {
						// 2.判断非0打头的月份是否合法
						int vMonth = Integer.parseInt(month);
						if (vMonth != 10 && vMonth != 11 && vMonth != 12) {
							return false;
						}
					}
					// 判断日期
					// 1.判断日期
					if (day != null && !str.equals("")) {
						if (day.startsWith("0")) {
							String units4Day = day.substring(1, 2);
							int vUnits4Day = Integer.parseInt(units4Day);
							if (vUnits4Day == 0) {
								return false;
							}
						} else {
							// 2.判断非0打头的日期是否合法
							int vDay = Integer.parseInt(day);
							if (vDay < 10 || vDay > 31) {
								return false;
							}
						}
					}
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

//	##引入包：import org.apache.commons.lang3.time.DateUtils;
	private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy年MM月dd日", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm",
			"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyyMMdd", "yyyyMM" };

	public static Date parseDate(String string) {
		if (string == null) {
			return null;
		}
		try {
			return DateUtils.parseDate(string, parsePatterns);
		} catch (ParseException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 生成业务流水号 系统标识（sysFlg.length位）+时间（14位，年月日时分秒）+系统流水（randomCount位）
	 * 
	 * @param sysFlg      系统标识
	 * @param randomCount 随机数位数
	 * @return
	 */
	public static synchronized String createSerial(String sysFlg, int randomCount) {

		safeSleep(1);
//		SimpleDateFormat sdft = new SimpleDateFormat("yyMMddhhmmss");
		SimpleDateFormat sdft = new SimpleDateFormat("yyMMdd");
		Date nowdate = new Date();
		String str = sdft.format(nowdate);
		return sysFlg + str + RandomStringUtils.randomNumeric(randomCount);
	}

	/**
	 * 数字前面自动补零
	 * 
	 * @param number 数字
	 * @return
	 */
	public static String getNumberStr(Long number,int length) {
		NumberFormat formatter = NumberFormat.getNumberInstance();
		formatter.setMinimumIntegerDigits(length);
		formatter.setGroupingUsed(false);
		return formatter.format(number);
	}

	public static void safeSleep(long millis) {

		try {
			Thread.sleep(millis);

		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static boolean checkFieldAllNull(Object object) throws IllegalAccessException {
		for (Field f : object.getClass().getDeclaredFields()) {
			f.setAccessible(true);
			if (Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
				continue;
			}
			if (!isNull(f.get(object))) {
				return false;
			}
			f.setAccessible(false);
		}
		// 父类public属性
		for (Field f : object.getClass().getFields()) {
			f.setAccessible(true);
			if (Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
				continue;
			}
			if (!isNull(f.get(object))) {
				return false;
			}
			f.setAccessible(false);
		}
		return true;
	}

	public static boolean isNull(Object[] objs) {
		if (null == objs || 0 == objs.length)
			return true;
		return false;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static boolean isNull(Object obj) {
		if (null == obj || isNull(obj.toString()))
			return true;
		if (obj instanceof String && isNull((String) obj))
			return true;

		if (obj instanceof Collection && isNull((Collection) obj))
			return true;

		if (obj instanceof Map && isNull((Map) obj))
			return true;

		if (obj instanceof List && isNull((List) obj))
			return true;

		if (obj instanceof Object[] && isNull((Object[]) obj))
			return true;

		if (obj instanceof Integer && isNull((Integer) obj))
			return true;

		if (obj instanceof Long && isNull((Long) obj))
			return true;

		if (obj instanceof Double && isNull((Double) obj))
			return true;

		if (obj instanceof Short && isNull((Short) obj))
			return true;

		if (obj instanceof Float && isNull((Float) obj))
			return true;

		if (obj instanceof Boolean && isNull((Boolean) obj))
			return true;

		if (obj instanceof Boolean && isNull((Byte) obj))
			return true;

		return false;
	}

	public static boolean isNotNull(Object obj) {
		return !isNull(obj);
	}

	public static boolean isNull(String str) {

		return null == str || "".equals(str.trim()) || "null".equals(str.toLowerCase());
	}

	public static boolean isNull(@SuppressWarnings("rawtypes") Collection collection) {
		if (null == collection || 0 == collection.size())
			return true;
		return false;
	}

	public static boolean isNull(List<Object> list) {
		if (null == list || 0 == list.size())
			return true;
		return false;
	}

	public static boolean isNull(@SuppressWarnings("rawtypes") Map map) {
		if (null == map || 0 == map.size())
			return true;
		return false;
	}

	public static boolean isNull(Integer integer) {
		if (null == integer || 0 == integer)
			return true;
		return false;
	}

	public static boolean isNull(Long longs) {
		if (null == longs || 0 == longs)
			return true;
		return false;
	}

	public static boolean isNull(Double d) {
		if (null == d || 0 == d)
			return true;
		return false;
	}

	public static boolean isNull(Short s) {
		if (null == s || 0 == s)
			return true;
		return false;
	}

	public static boolean isNull(Float f) {
		if (null == f || 0 == f)
			return true;
		return false;
	}

	public static boolean isNull(Boolean b) {
		if (null == b || false == b)
			return true;
		return false;
	}

	public static boolean isNull(Byte b) {
		if (null == b || 0 == b)
			return true;
		return false;
	}

	/**
	 * 获取一个类和其父类的所有属性
	 * 
	 * @param clazz
	 * @return
	 */
	public static List<Field> findAllFieldsOfSelfAndSuperClass(Class clazz) {
		Field[] fields = null;
		List fieldList = new ArrayList();
		while (true) {
			if (clazz == null) {
				break;
			} else {
				fields = clazz.getDeclaredFields();
				for (int i = 0; i < fields.length; i++) {
					fieldList.add(fields[i]);
				}
				clazz = clazz.getSuperclass();
			}
		}
		return fieldList;
	}

	/**
	 * 把一个Bean对象转换成Map对象</br>
	 * 
	 * @param clazz
	 * @param ignores
	 * @return
	 * @throws IllegalAccessException
	 */
	public static Map convertBean2Map(Object obj, String[] ignores) {
		Map map = new HashMap();
		Class clazz = obj.getClass();
		List<Field> fieldList = findAllFieldsOfSelfAndSuperClass(clazz);
		Field field = null;
		try {
			for (int i = 0; i < fieldList.size(); i++) {
				field = fieldList.get(i);
				// 定义fieldName是否在拷贝忽略的范畴内
				boolean flag = false;
				if (ignores != null && ignores.length != 0) {
					flag = isExistOfIgnores(field.getName(), ignores);
				}
				if (!flag) {
					Object value = getProperty(obj, field.getName());
					if (null != value && !StringUtils.EMPTY.equals(value.toString())) {
						map.put(field.getName(), getProperty(obj, field.getName()));
					}
				}
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 把一个Bean对象转换成Map对象</br>
	 * 
	 * @param clazz
	 * @return
	 */
	public static Map convertBean2Map(Object obj) {
		return convertBean2Map(obj, null);
	}

	public static Map convertBean2MapForIngoreserialVersionUID(Object obj) {
		return convertBean2Map(obj, new String[] { "serialVersionUID" });
	}

	/**
	 * 判断fieldName是否是ignores中排除的
	 * 
	 * @param fieldName
	 * @param ignores
	 * @return
	 */
	private static boolean isExistOfIgnores(String fieldName, String[] ignores) {
		boolean flag = false;
		for (String str : ignores) {
			if (str.equals(fieldName)) {
				flag = true;
				break;
			}
		}
		return flag;
	}

	public static PropertyDescriptor getPropertyDescriptor(Class clazz, String propertyName) {
		StringBuffer sb = new StringBuffer();// 构建一个可变字符串用来构建方法名称
		Method setMethod = null;
		Method getMethod = null;
		PropertyDescriptor pd = null;
		try {
			Field f = clazz.getDeclaredField(propertyName);// 根据字段名来获取字段
			if (f != null) {
				// 构建方法的后缀
				String methodEnd = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
				sb.append("set" + methodEnd);// 构建set方法
				setMethod = clazz.getDeclaredMethod(sb.toString(), new Class[] { f.getType() });
				sb.delete(0, sb.length());// 清空整个可变字符串
				sb.append("get" + methodEnd);// 构建get方法
				// 构建get 方法
				getMethod = clazz.getDeclaredMethod(sb.toString(), new Class[] {});
				// 构建一个属性描述器 把对应属性 propertyName 的 get 和 set 方法保存到属性描述器中
				pd = new PropertyDescriptor(propertyName, getMethod, setMethod);
			}
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return pd;
	}

	@SuppressWarnings("unchecked")
	public static void setProperty(Object obj, String propertyName, Object value) {
		Class<?> clazz = obj.getClass();// 获取对象的类型
		PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);// 获取 clazz
																			// 类型中的
																			// propertyName
																			// 的属性描述器
		Method setMethod = pd.getWriteMethod();// 从属性描述器中获取 set 方法
		try {
			setMethod.invoke(obj, new Object[] { value });// 调用 set 方法将传入的value值保存属性中去
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static Object getProperty(Object obj, String propertyName) {
		Class clazz = obj.getClass();// 获取对象的类型
		PropertyDescriptor pd = getPropertyDescriptor(clazz, propertyName);// 获取 clazz
																			// 类型中的
																			// propertyName
																			// 的属性描述器
		Method getMethod = pd.getReadMethod();// 从属性描述器中获取 get 方法
		Object value = null;
		try {
			value = getMethod.invoke(obj, new Object[] {});// 调用方法获取方法的返回值
		} catch (Exception e) {
			e.printStackTrace();
		}
		return value;// 返回值
	}
	
	/**
	 * 根据起始日期和间隔时间计算结束日期
	 * 
	 * @param sDate开始时间
	 * 
	 * @param days间隔时间
	 * 
	 * @return 结束时间
	 * */
	public static Date calculateEndDate(Date sDate, int days)
	{
		//将开始时间赋给日历实例
		Calendar sCalendar = Calendar.getInstance();
		sCalendar.setTime(sDate);
		//计算结束时间
		sCalendar.add(Calendar.DATE, days);
		//返回Date类型结束时间
		return sCalendar.getTime();
	}

}
