package de.tools;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 
 * @author VogelT
 *
 */

public class ReflectClass {

	private final Object m_workObject;
	public Object getWorkObject() { return m_workObject; }
	
	/**
	 * 
	 * @param method
	 * @param arg
	 */
	public void setMethod(String method, Object arg) {
		setMethod(method, new Object[]{arg});
	}
	
	/**
	 * 
	 * @param method
	 * @param arg
	 */
	public void setMethod(String method, Object[] arg) {
		try {
        	
        	@SuppressWarnings("rawtypes")
			Class[] parameterTypes = getParameterTypes(method);
        	Method setter = getWorkObject().getClass().getMethod(method, parameterTypes);

        	setter.invoke(getWorkObject(), arg);
        	
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void set(String fieldname, Object value) {
		try {
			Field field = getWorkObject().getClass().getDeclaredField(fieldname);
			
			if (field == null) {
				field = getWorkObject().getClass().getField(fieldname);
				
			}
			field.setAccessible(true);
			field.set(getWorkObject(), value);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public Object get(String fieldname) {
		Object result = null;
		//System.out.println("Fieldname: " + fieldname);
		
		if (getUpperSearch()) {
			fieldname = fieldname.trim().toUpperCase();
		} else {
			fieldname = fieldname.trim().toLowerCase();
		}
		
		try {
			if(fieldname.startsWith("serial")) {
				return result;
			}
			
			Field field = getWorkObject().getClass().getDeclaredField(fieldname);
			
			//String clazzType = field.getType().getName();
			if (field == null) {
				field = getWorkObject().getClass().getField(fieldname);
			}
			
			if (field != null) {
				field.setAccessible(true);
				result = field.get(getWorkObject());
			}
					
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 
	 * @param method
	 * @return
	 */
//	public Object getMethod(String method) {
//		Object result = null;
//		
//		try {
//	
//			
//			
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return result;
//	}
	
	/**
	 * 
	 * @param methodSearch
	 * @return
	 */
	public Class<?> getReturnType(String methodSearch) {
		Class<?> returnTypes = null;
		
		for ( Method method : getWorkObject().getClass().getMethods() ) {
	      //String returnString = method.getReturnType().getName();

	      if (method.getName().equals(methodSearch)) {
	    	  returnTypes = method.getReturnType();
	    	  break;
	      }
		}
	    return returnTypes;
	}
	
	/**
	 * 
	 * @param methodSearch
	 * @return
	 */
	public Class<?>[] getParameterTypes(String methodSearch) {
		Class<?>[] parameterTypes = null;
		
		for ( Method method : getWorkObject().getClass().getMethods() ) {
	      //String returnString = method.getReturnType().getName();

	      if (method.getName().equals(methodSearch)) {
	    	  parameterTypes = method.getParameterTypes();
	    	  break;
	      }
	    }
		return parameterTypes;
	}

	/**
	 * showMethods
	 */
	public void showMethods() {
	    for ( Method method : getWorkObject().getClass().getMethods() ) {
	      String returnString = method.getReturnType().getName();
	      System.out.print( returnString + " " + method.getName() + "(" );

	      Class<?>[] parameterTypes = method.getParameterTypes();

	      for ( int k = 0; k < parameterTypes.length; k++ ) {
	        String parameterString = parameterTypes[k].getName();
	        System.out.print( " " + parameterString );

	        if ( k < parameterTypes.length - 1 )
	          System.out.print( ", " );
	      }
	      System.out.print( " )" );

	      Class<?>[] exceptions = method.getExceptionTypes();

	      if ( exceptions.length > 0 ) {
	        System.out.print( " throws " );
	        for ( int k = 0; k < exceptions.length; k++ ) {
	          System.out.print( exceptions[k].getName() );
	          if ( k < exceptions.length - 1)
	            System.out.print( ", " );
	        }
	      }
	      System.out.println();
	    }
	}

	public boolean m_upperSearch = false;
	public boolean getUpperSearch() { return m_upperSearch; }

	public ReflectClass(Object o) {
		this.m_workObject = o;

	}
	
	public ReflectClass(Object o, boolean upperSearch) {
		this.m_workObject = o;
		this.m_upperSearch = upperSearch;
	}
	
	public static void main(String[] arg) {
		
//		MenuBarButtonExpressions barExpressions = new MenuBarButtonExpressions(MenuBarButtonAction.PRINT, "Text", "/image");
//		ReflectClass reflectClass = new ReflectClass(barExpressions);
//		reflectClass.showMethods();
//		
//		reflectClass.showFields();
		
	}

	public void showFields() {
		
		Field[] fields = getWorkObject().getClass().getDeclaredFields();
		
		for (Field field : fields) {
			System.out.println(field.getName());
		}
		
	}
	
	public List<String> getAllDeclaredFields() {
		List<String> resultList = new ArrayList<String>();
		Field[] fields = getWorkObject().getClass().getDeclaredFields();
		
		for (Field field : fields) {
			resultList.add(field.getName());
		}
		return resultList;
	}
	
	public List<String> getAllFields() {
		List<String> resultList = new ArrayList<String>();
		Field[] fields = getWorkObject().getClass().getFields();
		
		for (Field field : fields) {
			resultList.add(field.getName());
		}
		return resultList;
	}
	
	public String getType(String fieldname) {
		String result = null;
		try {
			
			if (fieldname == null || fieldname.trim().length() == 0)
				return "";
			
			if (getUpperSearch()) {
				result = getWorkObject().getClass().getDeclaredField(fieldname.trim().toUpperCase()).getType().getName();
			} else {
				result = getWorkObject().getClass().getDeclaredField(fieldname.trim().toLowerCase()).getType().getName();	
			}
		} catch (Exception e) {
			e.printStackTrace();
			return "";
		}
		return result;
	}

}
