package nc.bs.hz.utils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import org.mozilla.javascript.edu.emory.mathcs.backport.java.util.Arrays;

import nc.vo.pub.SuperVO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.lang.UFDate;
import nc.vo.pub.lang.UFDateTime;
import nc.vo.pub.lang.UFDouble;
import uap.json.JSONArray;
import uap.json.JSONObject;

public class HzJson2ObjectUtil {

	private String obj2String(Object object) {
		if (object != null) {
			return object.toString();
		}
		return null;
	}

	private String UFDouble2String(UFDouble value) {
		if (value != null) {
			return Double.toString(value.getDouble());
		}
		return null;
	}

	private UFDouble String2UFDouble(Object value) {
		if (value != null) {
			return new UFDouble(value.toString());
		}
		return null;
	}

	private UFBoolean object2UFBoolean(Object value) {
		if (value != null) {
			return new UFBoolean(value.toString());
		}
		return null;
	}

	private UFDate object2UFDate(String pattern, Object value) {
		if (value != null && pattern != null) {
			DateFormat df = new SimpleDateFormat(pattern);
			Date date = null;
			try {
				date = df.parse(value.toString());
			} catch (ParseException e) {
				e.printStackTrace();
			}
			return new UFDate(date);
		}
		return null;
	}

	private UFDateTime object2UFDateTime(String pattern, Object value) {
		if (value != null && pattern != null) {
			DateFormat df = new SimpleDateFormat(pattern);
			Date date = null;
			try {
				date = df.parse(value.toString());
			} catch (ParseException e) {
				e.printStackTrace();
			}
			return new UFDateTime(date);
		}
		return null;
	}

	private String UFData2String(Object object) {

		if (object instanceof UFDouble) {
			return UFDouble2String((UFDouble) object);
		} else if (object instanceof UFDate) {
			return obj2String(object);
		} else if (object instanceof UFBoolean) {
			return obj2String(object);
		} else if (object instanceof UFDateTime) {
			return obj2String(object);
		}
		return object == null ? null : object.toString();
	}

	public Object String2UFData(Object object, String value) {
		String datetimePattern = "yyyy-MM-dd HH:mm:ss";
		String datePattern = "yyyy-MM-dd";
		if (object instanceof UFDouble) {
			return String2UFDouble(value);
		} else if (object instanceof UFDate) {
			return object2UFDate(datePattern, value);
		} else if (object instanceof UFBoolean) {
			return object2UFBoolean(value);
		} else if (object instanceof UFDateTime) {
			return object2UFDateTime(datetimePattern, value);
		}
		return value;
	}

	/**
	 * Except Integer, other attributes are both converted to String.
	 * 
	 * @param superVO
	 * @return Map<String, Object>
	 */
//	public Map<String, Object> SuperVO2Map(SuperVO superVO) {
//		if (superVO == null) {
//			return null;
//		}
//		Map<String, Object> returnMap = new HashMap<String, Object>();
//		String[] attributeNames = superVO.getAttributeNames();
//		for (String attrName : attributeNames) {
//			if (superVO.getAttributeValue(attrName) instanceof Integer) {
//				returnMap.put(attrName, superVO.getAttributeValue(attrName));
//			}if (superVO.getAttributeValue(attrName) instanceof Map) {
//				Map map = (Map) superVO.getAttributeValue(attrName);
//				for (Object key : map.keySet()) {
//					if (key != null && !"".equals(key.toString())) {
//						returnMap.put(key.toString(), map.get(key));
//					}
//				}
//			} else {
//				returnMap.put(attrName,
//						UFData2String(superVO.getAttributeValue(attrName)));
//			}
//		}
//		Field[] fields = superVO.getClass().getDeclaredFields();
//		for (Field f : fields) {
//			if (f.isAnnotationPresent(SerializablefilterArray.class)) {
//				SerializablefilterArray serializable = f
//						.getAnnotation(SerializablefilterArray.class);
//				boolean filter = serializable.value();
//				if (!filter) {
//					if (f.getType().isArray()) {
//						try {
//							// 设置访问权限
//							f.setAccessible(true);
//							Object[] filterArray = (Object[]) f.get(superVO);
//							for (int i = 0; i < filterArray.length; i++) {
//								Object object = filterArray[i];
//								if (object != null
//										&& !"".equals(object.toString())) {
//									returnMap.remove(object.toString());
//								}
//							}
//						} catch (IllegalArgumentException e) {
//							e.printStackTrace();
//							Logger.error(e);
//						} catch (IllegalAccessException e) {
//							e.printStackTrace();
//							Logger.error(e);
//						}
//					} 
//				}
//			}
//			// 因为字段和注解是一对多的，此处万不可用else if
//			if (f.isAnnotationPresent(Serializablefilter.class)) {
//				Serializablefilter serializable = f
//						.getAnnotation(Serializablefilter.class);
//				boolean filter = serializable.value();
//				if (!filter) {
//					returnMap.remove(f.getName());
//				}
//			}
//		}
//		return returnMap;
//	}

	/**
	 * 
	 * @param superVOs
	 * @return List<Map<String, Object>>
	 */
//	public List<Map<String, Object>> SuperVOArray2MapList(SuperVO[] superVOs) {
//		if (superVOs == null || 0 == superVOs.length) {
//			return null;
//		}
//		List<Map<String, Object>> dataMapList = new ArrayList<Map<String, Object>>();
//		Map<String, Object> dataMap = null;
//		for (SuperVO superVO : superVOs) {
//			dataMap = SuperVO2Map(superVO);
//			if (dataMap != null) {
//				dataMapList.add(dataMap);
//			}
//		}
//		return dataMapList;
//	}

//	public JSONObject superVO2JsonObject(SuperVO superVO) {
//		Map<String, Object> dataMap = SuperVO2Map(superVO);
//		if (dataMap != null) {
//			return new JSONObject(dataMap);
//		}
//		return null;
//	}

	public SuperVO json2SuperVO(JSONObject jsonObject) throws Exception {
		return json2Object(jsonObject, SuperVO.class);
	}

	public List<SuperVO> json2SuperVOList(JSONArray jsonObject,
			Class<? extends SuperVO> clazz) throws Exception {
		List<SuperVO> result = new ArrayList<>();
		for (int i = 0; i < jsonObject.length(); i++) {
			JSONObject tempJson = jsonObject.getJSONObject(i);
			result.add(json2Object(tempJson, clazz));
		}
		return result;
	}

	public SuperVO map2SuperVO(Map<String, Object> map) throws Exception {
		JSONObject jsonObject = new JSONObject(map);
		if (jsonObject != null) {
			return json2SuperVO(jsonObject);
		}
		return null;
	}

	public <T> T json2Object(String[] vos, String[] jsons,
			JSONObject jsonObject, Class<? extends Object> beanClass)
			throws Exception {
		if (jsonObject == null) {
			return null;
		}
		T object = (T) beanClass.newInstance();
		BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
		PropertyDescriptor[] propertyDescriptors = beanInfo
				.getPropertyDescriptors();
		String datetimePattern = "yyyy-MM-dd HH:mm:ss";
		String datePattern = "yyyy-MM-dd";
		Method setter = null;
		String properTypeName = null;
		String value = null;
		for (PropertyDescriptor property : propertyDescriptors) {
			/*
			 * 调试位置 if ("id".equals(property.getName())) {
			 * System.out.println("a"); }
			 */
			setter = property.getWriteMethod();
			properTypeName = property.getPropertyType().getName();
			String propertyName = property.getName();
			int voindex = Arrays.asList(vos).indexOf(propertyName);
			if (voindex < 0) {
				continue;
			}
			value = jsonObject.getString(jsons[voindex]);
			// 值都没有你往下走 个啥？ pjs 2019年11月14日08:35:10
			if (value == null || "".equals(value)) {
				continue;
			}
			if (object instanceof SuperVO && setter != null
					&& String.class.getName().equals(properTypeName)) {// add by
																		// pjs
																		// 2019年6月11日09:53:18
																		// 只有字符类型才能直接设值
				((SuperVO) object).setAttributeValue(propertyName, value);
				// setter.invoke(object, value);
			} else {
				if (setter != null) {
					if (properTypeName.equals(UFDouble.class.getName())) {
						setter.invoke(object, String2UFDouble(value));
					} else if (properTypeName.equals(UFBoolean.class.getName())) {
						setter.invoke(object, object2UFBoolean(value));
					} else if (properTypeName.equals(UFDate.class.getName())) {
						setter.invoke(object, object2UFDate(datePattern, value));
					} else if (properTypeName
							.equals(UFDateTime.class.getName())) {
						if (value.length() <= 10) {
							value = value + " 00:00:00";
						}
						setter.invoke(object,
								object2UFDateTime(datetimePattern, value));
					} else if (properTypeName.equals(String.class.getName())) {
						setter.invoke(object, value);
					} else if (properTypeName.equals(Integer.class.getName())) {
						setter.invoke(object,
								jsonObject.getInt(propertyName));
					} else if (properTypeName.equals(Double.class.getName())) {
						setter.invoke(object,
								jsonObject.getDouble(propertyName));
					} else if (properTypeName.equals(java.sql.Date.class
							.getName())) {
						setter.invoke(object, jsonObject.get(propertyName));
					} else if (properTypeName.equals(Long.class.getName())) {
						setter.invoke(object, jsonObject.getLong(propertyName));
					}
				}
			}

		}

		return object;

	}

	public <T> T json2Object(JSONObject jsonObject, Class<T> beanClass)
			throws Exception {
		if (jsonObject == null) {
			return null;
		}
		T object = beanClass.newInstance();
		BeanInfo beanInfo = Introspector.getBeanInfo(object.getClass());
		PropertyDescriptor[] propertyDescriptors = beanInfo
				.getPropertyDescriptors();
		String datetimePattern = "yyyy-MM-dd HH:mm:ss";
		String datePattern = "yyyy-MM-dd";
		Method setter = null;
		String properTypeName = null;
		String value = null;
		for (PropertyDescriptor property : propertyDescriptors) {
			/*
			 * 调试位置 if ("id".equals(property.getName())) {
			 * System.out.println("a"); }
			 */
			setter = property.getWriteMethod();
			properTypeName = property.getPropertyType().getName();
			try {
				value =(String)jsonObject.get(property.getName());				
			}catch (NoSuchElementException e) {
				continue;
			} 
			if (value == null || "".equals(value)) {
				continue;
			}
			// 值都没有你往下走 个啥？ pjs 2019年11月14日08:35:10
			
//			if (object instanceof SuperVO && setter != null
//					&& String.class.getName().equals(properTypeName)) {// add by
//																		// pjs
//																		// 2019年6月11日09:53:18
//																		// 只有字符类型才能直接设值
//				((SuperVO) object).setAttributeValue(property.getName(), value);
//				// setter.invoke(object, value);
//			} else {
				if (setter != null) {
					if (properTypeName.equals(UFDouble.class.getName())) {
						setter.invoke(object, String2UFDouble(value));
					} else if (properTypeName.equals(UFBoolean.class.getName())) {
						setter.invoke(object, object2UFBoolean(value));
					} else if (properTypeName.equals(UFDate.class.getName())) {
						setter.invoke(object, object2UFDate(datePattern, value));
					} else if (properTypeName
							.equals(UFDateTime.class.getName())) {
						if (value.length() <= 10) {
							value = value + " 00:00:00";
						}
						setter.invoke(object,
								object2UFDateTime(datetimePattern, value));
					} else if (properTypeName.equals(String.class.getName())) {
						setter.invoke(object, value);
					} else if (properTypeName.equals(Integer.class.getName())) {
						setter.invoke(object,
								jsonObject.getInt(property.getName()));
					} else if (properTypeName.equals(Double.class.getName())) {
						setter.invoke(object,
								jsonObject.getDouble(property.getName()));
					} else if (properTypeName.equals(java.sql.Date.class
							.getName())) {
						setter.invoke(object,
								jsonObject.get(property.getName()));
					} else if (properTypeName.equals(Long.class.getName())) {
						setter.invoke(object,
								jsonObject.getLong(property.getName()));
					}
				}
//			}

		}

		return object;

	}

}
