package net.mgsx.game.core.ui.accessors;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import com.badlogic.gdx.utils.Array;

import net.mgsx.game.core.annotations.Editable;
import net.mgsx.game.core.helpers.ReflectionHelper;

public class AccessorScanner {

	private static void scanField(Array<Accessor> accessors, Object entity, Field field, boolean annotationBasedOnly)
	{
		if(Modifier.isStatic(field.getModifiers())) return;
		
		if(annotationBasedOnly){
			Editable editable = field.getAnnotation(Editable.class);
			if(editable == null){
				return;
			}
			if(editable.value().isEmpty())
				accessors.add(new FieldAccessor(entity, field));
			else
				accessors.add(new FieldAccessor(entity, field, editable.value()));
		}
		else
		{
			accessors.add(new FieldAccessor(entity, field));
		}
	}
	
	private static void scanMethod(Array<Accessor> accessors, Object entity, Method method, boolean annotationBasedOnly)
	{
		if(Modifier.isStatic(method.getModifiers())) return;
		
		if(annotationBasedOnly){
			Editable editable = method.getAnnotation(Editable.class);
			if(editable == null){
				return;
			}
			if(method.getReturnType() != void.class) return;
			if(method.getParameterCount() > 0) return;
			if(editable.value().isEmpty())
				accessors.add(new VoidAccessor(entity, method));
			else
				accessors.add(new VoidAccessor(entity, method, editable.value()));
		}
		else
		{
			if(method.getName().startsWith("set") && method.getName().length() > 3 && method.getParameterCount() == 1)
			{
				String getterName = "g" + method.getName().substring(1);
				Method getter = ReflectionHelper.method(entity.getClass(), getterName);
				if(getter == null || getter.getReturnType() != method.getParameterTypes()[0]){
					// try boolean pattern setX/isX
					getterName = "is" + method.getName().substring(3);
					getter = ReflectionHelper.method(entity.getClass(), getterName);
				}
				if(getter != null && getter.getReturnType() == method.getParameterTypes()[0]){
					String name = method.getName().substring(3,4).toLowerCase() + method.getName().substring(4);
					accessors.add(new MethodAccessor(entity, name, getter, method));
				}
			}
		}
	}

	
	public static Array<Accessor> scan(Object entity, boolean annotationBasedOnly)
	{
		Array<Accessor> accessors = new Array<Accessor>();
		
		// scan fields
		for(Field field : entity.getClass().getFields())
		{
			scanField(accessors, entity, field, annotationBasedOnly);
		}
		
		// scan getter/setter pattern
		for(Method method : entity.getClass().getMethods())
		{
			scanMethod(accessors, entity, method, annotationBasedOnly);
			
		}
		return accessors;
	}
}

@@ -1036,36 +1036,8 @@
 %0A%09%09%0A
-%09%09if(annotationBasedOnly)%7B%0A%09
 %09%09Ed
@@ -1086,33 +1086,32 @@
 table.class);%0A%09%09
-%09
 if(editable == n
@@ -1105,36 +1105,58 @@
 editable == null
+ && annotationBasedOnly
 )%7B%0A
-%09
 %09%09%09return;%0A%09%09%09%7D%0A
@@ -1152,25 +1152,46 @@
 turn;%0A%09%09
-%09
 %7D%0A%09%09
+%0A%09
 %09if(
+editable != null && 
 method.g
@@ -1205,17 +1205,17 @@
 nType() 
-!
+=
 = void.c
@@ -1218,32 +1218,20 @@
 id.class
-) return;%0A%09%09%09if(
+ && 
 method.g
@@ -1253,20 +1253,14 @@
 t() 
-%3E 0) return;
+== 0)%7B
 %0A%09%09%09
@@ -1428,26 +1428,17 @@
 ;%0A%09%09%7D%0A%09%09
-else%0A%09%09%7B%0A%09
+%0A
 %09%09if(met
@@ -1542,17 +1542,15 @@
  1)%0A
-%09
 %09%09%7B%0A%09%09%09
-%09
 Stri
@@ -1602,17 +1602,16 @@
 ing(1);%0A
-%09
 %09%09%09Metho
@@ -1676,25 +1676,24 @@
 erName);%0A%09%09%09
-%09
 if(getter ==
@@ -1755,25 +1755,24 @@
 ypes()%5B0%5D)%7B%0A
-%09
 %09%09%09%09// try b
@@ -1795,25 +1795,24 @@
 etX/isX%0A%09%09%09%09
-%09
 getterName =
@@ -1850,17 +1850,16 @@
 ing(3);%0A
-%09
 %09%09%09%09gett
@@ -1922,20 +1922,18 @@
 me);%0A%09%09%09
-%09
 %7D%0A
-%09
 %09%09%09if(ge
@@ -2010,17 +2010,16 @@
 %5D)%7B%0A%09%09%09%09
-%09
 String n
@@ -2107,17 +2107,16 @@
 4);%0A%09%09%09%09
-%09
 accessor
@@ -2176,14 +2176,8 @@
 ));%0A
-%09%09%09%09%7D%0A
 %09%09%09%7D

fix scan methods