package nc.bs.yypub.tools.json;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.Iterator;

import nc.vo.erm.costshare.CShareDetailVO;
import nc.vo.jcom.lang.StringUtil;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.CircularlyAccessibleValueObject;
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 JSONTools {
	
	private JSONTools() {}
	
	
	@SuppressWarnings("unchecked")
	public static <T extends AggregatedValueObject> T[] jsonToAggVOs(JSONArray jsonArr, Class<? extends AggregatedValueObject> aggVOClass, Class<? extends CircularlyAccessibleValueObject> headVOClass, Class<? extends CircularlyAccessibleValueObject> bodyVOClass) throws BusinessException {
		T[] aggVO = null;
		try {
			if(jsonArr == null) {
				return null;
			}
			int len = jsonArr.length(),bLen;
			aggVO = (T[]) Array.newInstance(aggVOClass, jsonArr.length());
			CircularlyAccessibleValueObject headVO;
			CircularlyAccessibleValueObject[] bodyVOs;
			CircularlyAccessibleValueObject bodyVO;
			Iterator<String> it;
			Iterator<String> bIt;
			String attributeName;
			Object value;
			JSONObject billObj;
			JSONObject bodyJsonObj;
			JSONArray bodyJsonObjs;
			for (int i = 0; i < len; i++) {
				billObj = (JSONObject) jsonArr.get(i);
				if(billObj!=null){
					headVO = headVOClass.newInstance();
					bodyVOs = null;
					it = (Iterator<String>)billObj.keys();
					while(it.hasNext()){
						attributeName = it.next();
						if(StringUtil.isEmptyWithTrim(attributeName)){
							continue;
						}
						value = billObj.get(attributeName);
						if(value==null || StringUtil.isEmptyWithTrim(value.toString())){
							continue;
						}
						if(!"billitems".equalsIgnoreCase(attributeName)){
							headVO.setAttributeValue(attributeName, value);
							continue;
						}
						bodyJsonObj = new JSONObject(value.toString());
						bodyJsonObjs = (JSONArray)bodyJsonObj.get("billitem");
						if(bodyJsonObjs==null || bodyJsonObjs.length()==0){
							continue;
						}
						bLen = bodyJsonObjs.length();
						bodyVOs = (CircularlyAccessibleValueObject[]) Array.newInstance(bodyVOClass,bLen);
						for(int j=0;j<bLen;j++){
							bodyJsonObj = (JSONObject)bodyJsonObjs.get(j);
							if(bodyJsonObj==null){
								continue;
							}
							bodyVO = bodyVOClass.newInstance();
							bIt = bodyJsonObj.keys();
							while(bIt.hasNext()){
								attributeName = bIt.next();
								if(StringUtil.isEmptyWithTrim(attributeName)){
									continue;
								}
								value = bodyJsonObj.get(attributeName);
								if(value==null || StringUtil.isEmptyWithTrim(value.toString())){
									continue;
								}
								bodyVO.setAttributeValue(attributeName, value);
							}
							bodyVOs[j] = bodyVO;
						}
					}
					aggVO[i] = (T) aggVOClass.newInstance();
					aggVO[i].setParentVO(headVO);
					aggVO[i].setChildrenVO(bodyVOs);
				}
			}
		} catch (Exception e) {
			if(e instanceof BusinessException) { 
				throw (BusinessException)e;
			} else {
				throw new BusinessException(e);
			}
		}
		return aggVO;
	}
	
	@SuppressWarnings("unchecked")
	public static <T extends AggregatedValueObject> T[] jsonToAggVOs(JSONArray jsonArr, Class<? extends AggregatedValueObject> aggVOClass, Class<? extends CircularlyAccessibleValueObject> headVOClass, Class<? extends CircularlyAccessibleValueObject> bodyVOClass,String billtype) throws BusinessException {
		T[] aggVO = null;
		try {
			if(jsonArr == null) {
				return null;
			}
			int len = jsonArr.length(),bLen;
			aggVO = (T[]) Array.newInstance(aggVOClass, jsonArr.length());
			CircularlyAccessibleValueObject headVO;
			CircularlyAccessibleValueObject[] bodyVOs;
			CircularlyAccessibleValueObject bodyVO;
			Iterator<String> it;
			Iterator<String> bIt;
			String attributeName;
			Object value;
			JSONObject billObj;
			JSONObject bodyJsonObj;
			JSONArray bodyJsonObjs;
			Field[] headFields = headVOClass.getFields();
			for (int i = 0; i < len; i++) {
				billObj = (JSONObject) jsonArr.get(i);
				if(billObj!=null){
					headVO = headVOClass.newInstance();
					bodyVOs = null;
					it = (Iterator<String>)billObj.keys();
					while(it.hasNext()){
						attributeName = it.next();
						if(StringUtil.isEmptyWithTrim(attributeName)){
							continue;
						}
						value = billObj.get(attributeName);
						if(value==null || StringUtil.isEmptyWithTrim(value.toString())){
							continue;
						}
						if(!"billitems".equalsIgnoreCase(attributeName)){//±νΝ·
							if("org_org".equalsIgnoreCase(attributeName)){
								attributeName = "pk_org";
							}
							for (int j = 0; j < headFields.length; j++) {
								Field field = headFields[j];
								if(attributeName.equals(headFields[j].getName())){
									Class type = field.getType();
									if(type == String.class) {
										headVO.setAttributeValue(attributeName, value);
									} else if(type == Integer.class) {
										headVO.setAttributeValue(attributeName, Integer.parseInt(value.toString()));
									} else if(type == Double.class) {
										headVO.setAttributeValue(attributeName, Double.parseDouble(value.toString()));
									} else if(type == Boolean.class) {
										headVO.setAttributeValue(attributeName, Boolean.parseBoolean(value.toString()));
									} else if(type == UFDouble.class) {
										headVO.setAttributeValue(attributeName, new UFDouble(value.toString()));
									} else if(type == UFBoolean.class) {
										headVO.setAttributeValue(attributeName, new UFBoolean(value.toString()));
									} else if(type == UFDate.class) {
										headVO.setAttributeValue(attributeName, new UFDate(value.toString()));
									} else if(type == UFDateTime.class) {
										headVO.setAttributeValue(attributeName, new UFDateTime(value.toString()));
									} else{
										headVO.setAttributeValue(attributeName, value);
									}
									break;
								}
								
							}
							continue;
						}
						bodyJsonObj = new JSONObject(value.toString());
						bodyJsonObjs = (JSONArray)bodyJsonObj.get("billitem");
						if(bodyJsonObjs==null || bodyJsonObjs.length()==0){
							continue;
						}
						bLen = bodyJsonObjs.length();
						bodyVOs = (CircularlyAccessibleValueObject[]) Array.newInstance(bodyVOClass,bLen);
						for(int j=0;j<bLen;j++){
							bodyJsonObj = (JSONObject)bodyJsonObjs.get(j);
							if(bodyJsonObj==null){
								continue;
							}
							bodyVO = bodyVOClass.newInstance();
							bIt = bodyJsonObj.keys();
							while(bIt.hasNext()){
								attributeName = bIt.next();
								if(StringUtil.isEmptyWithTrim(attributeName)){
									continue;
								}
								value = bodyJsonObj.get(attributeName);
								if(value==null || StringUtil.isEmptyWithTrim(value.toString())){
									continue;
								}
								if("ysdate".equals(attributeName)){
									bodyVO.setAttributeValue(attributeName, new UFDate(value.toString()));
								}else if("assume_amount".equals(attributeName)){
									bodyVO.setAttributeValue(attributeName, new UFDouble(value.toString()));
								}else{
									bodyVO.setAttributeValue(attributeName, value);
								}
							}
							bodyVOs[j] = bodyVO;
						}
					}
					aggVO[i] = (T) aggVOClass.newInstance();
					aggVO[i].setParentVO(headVO);
					((nc.vo.ep.bx.BXVO)aggVO[i]).setcShareDetailVo((CShareDetailVO[])bodyVOs);
				}
			}
		} catch (Exception e) {
			if(e instanceof BusinessException) { 
				throw (BusinessException)e;
			} else {
				throw new BusinessException(e);
			}
		}
		return aggVO;
	}
	
}
