package gov.va.med.esr.service.external;

import gov.va.med.esr.service.external.person.EESummary;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.PropertyUtilsBean;

public class EEServiceFieldNameBuilder {

	public static void main(String[] args) throws Exception{
	
		Class thisClass = EESummary.class;
		List fields = getFields(thisClass, new ArrayList());
		//System.out.print("Checking MAIN " + fields.size());
		for ( int i=0; fields != null && i< fields.size(); i++)
		{
			if ( "serialVersionUID".equals(((Field)fields.get(i)).getName())) {
				continue;
			}
			//System.out.print("Checking MAIN " + ((Field)fields.get(i)).getName());
			//System.out.println("type " + fields[i].getType());
			try
			{
				printFieldDetails((Field)fields.get(i), "eeSummary");
			}
			catch(Exception e) {
				e.printStackTrace();
			}
		}

		
		/**
		EESummary eeSummary = new EESummary();
		
		DemographicInfo demographicInfo = new DemographicInfo();
		
		
		AddressCollection addressCollection = new AddressCollection();
		AddressInfo addressinfo = new AddressInfo();
		addressinfo.setAddressTypeCode("P");
		addressinfo.setCity("FairFax");

		AddressInfo addressinfo1 = new AddressInfo();
		addressinfo1.setAddressTypeCode("T");
		addressinfo1.setCity("Ashburn");
		AddressInfo[] arr = new AddressInfo[2];
		arr[0] = addressinfo;
		arr[1] = addressinfo1;
		addressCollection.setAddress(arr);
		ContactInfo contactInfo = new ContactInfo();
		contactInfo.setAddresses(addressCollection);
		demographicInfo.setContactInfo(contactInfo);
		eeSummary.setDemographics(demographicInfo);
		PropertyUtilsBean propUtils = new PropertyUtilsBean();
		Map map = propUtils.describe(eeSummary);
		String prefix = "eeSummary";
		Iterator itr = map.keySet().iterator();
		
		while(itr.hasNext() )
		{
			String keyName = (String)itr.next();
			if ("class".equals(keyName)) {
				continue;
			}
			
			Object value = map.get(keyName);
			if ( value == null ) {
				continue;
			} else if (value instanceof ExternalComponent) {
				applyRoleToObject(value, prefix+"." + keyName, eeSummary, keyName);
			} else if (value instanceof Array ) {
				System.out.println(" Object Type Array:" + value);
			} else if (value instanceof Object[] ) {
				Object[] objArr = (Object[]) value;
				for ( int i=0; i< objArr.length;i++  ) {
					Object thisObj = objArr[i];
					applyRoleToObject(thisObj, prefix+"." + keyName, eeSummary, keyName);
				}
				
			}else {
				
				if (value instanceof String ) {
					System.out.println("prefix : " + prefix);
					
					System.out.println("Unknow Object Type :" + value);
				}
			}
		}
		
		
		
		
		System.out.println("output :" + map);
		**/
	}
	
	private static void applyRoleToObject(Object obj, String prefix, Object parentObject, String parentKeyName) throws Exception{
		PropertyUtilsBean propUtils = new PropertyUtilsBean();
		Map map = propUtils.describe(obj);
	
		
		boolean allisNull = true;
		Iterator itr = map.keySet().iterator();
		
		while(itr.hasNext() )
		{
			String keyName = (String)itr.next();
			if ("class".equals(keyName)) {
				continue;
			}
			
			Object value = map.get(keyName);
			if ( value == null ) {
				continue;
			} else if (value instanceof ExternalComponent) {
				applyRoleToObject(value, prefix+"." + keyName, obj, keyName);
			} else if (value instanceof Array ) {
				System.out.println(" Object Type Array:" + value);
			} else if (value instanceof Object[] ) {
				Object[] objArr = (Object[]) value;
				for ( int i=0; i< objArr.length;i++  ) {
					Object thisObj = objArr[i];
					applyRoleToObject(thisObj, prefix+"." + keyName, obj, keyName);
				}
				
			}else {
				if (value instanceof String ) {
					System.out.println("prefix : " + prefix + "." + keyName);
					propUtils.setSimpleProperty(obj, keyName, null);
					System.out.println("Unknow Object Type :" + value);
				}
			}
		}
		
		if ( allisNull ) { 
			System.out.println("Setting null to  :" + parentObject + " :" + parentKeyName);
			PropertyUtilsBean propUtils2 = new PropertyUtilsBean();
			propUtils2.setSimpleProperty(parentObject, parentKeyName, null);
			System.out.println("After  :" + parentObject + " :" + parentKeyName);
			}
	}
	
	
	private static void printFieldDetails(Field field, String namePrefix) throws Exception{
		//System.out.print("Checking :" + field.getType().toString() );
		String fieldType  = field.getType().toString();
		//class [Lgov
		//System.out.println("Checking Field :" + fieldType + " name :"+ field.getName() + " : index of gov:" + fieldType.indexOf("gov") );
		if ( fieldType.indexOf("gov") >= 0 )  {
			
			List fields = new ArrayList();;
 			if ( fieldType.indexOf("class [L") >= 0 ) {
 				String className = fieldType.substring(8, fieldType.length()-1);
 				//System.out.println("getting fields for class :"+ className );
 				fields = getFields(Class.forName(className), fields);
			}else {
				fields = getFields(field.getType(), fields);
			}
			
			
/**			 
 			String prefix = "";
 			if ( fieldType.indexOf("class [L") >= 0 ) {
 				System.out.print("before prefix :" + prefix);
 				prefix = namePrefix ;
 				prefix = prefix.substring(0, prefix.lastIndexOf("."));
 				System.out.println("After prefix :" + prefix);
 			} 
 **/				
			String prefix = namePrefix + "." + field.getName();
			if (fields.size() <= 0 ){
				System.out.println("Fields not found for**************** :" + fieldType + " name :"+ field.getName() + " : index of gov:" + fieldType.indexOf("gov") );
			}
			

			
			for ( int i=0; fields != null && i< fields.size(); i++)
			{
				if ( "serialVersionUID".equals(((Field)fields.get(i)).getName())) {
					continue;
				}
				printFieldDetails((Field)fields.get(i), prefix);
			}
		} else {
			System.out.println(namePrefix + "." + field.getName() + "	Type:" + field.getType());
		}
	}
	
	
	private static List getFields(Class classObj , List fields) {
		//ArrayList thisFields = (classObj.getDeclaredFields().
		//System.out.println("Checking fields :" +classObj);
		if (classObj == null || classObj.getDeclaredFields() == null ) {
			return fields;
		}
		
				fields.addAll(Arrays.asList(classObj.getDeclaredFields()));
				
			Class parentClass = classObj.getSuperclass();
			getFields(parentClass, fields);
		return fields;
	}
}
