package io.domisum.lib.auxiliumlib.util;

import io.domisum.lib.auxiliumlib.annotations.API;
import io.domisum.lib.auxiliumlib.exceptions.ProgrammingError;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@API
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class ReflectionUtil
{
	
	// INJECT
	@API
	public static void injectValue(Object object, String fieldName, Object value)
	{
		try
		{
			injectValueUncaught(object, fieldName, value);
		}
		catch(IllegalAccessException e)
		{
			throw new ProgrammingError(e);
		}
	}
	
	@API
	public static void injectValueUncaught(Object object, String fieldName, Object value)
		throws IllegalAccessException
	{
		for(var field : getAllFields(object))
			if(field.getName().equals(fieldName))
				field.set(object, value);
	}
	
	
	@API
	public static void injectValue(Object object, Class<?> valueClass, Object value)
	{
		try
		{
			injectValueUncaught(object, valueClass, value);
		}
		catch(IllegalAccessException e)
		{
			throw new ProgrammingError(e);
		}
	}
	
	@API
	public static void injectValueUncaught(Object object, Class<?> valueClass, Object value)
		throws IllegalAccessException
	{
		for(var field : getAllFields(object))
			if(field.getType().isAssignableFrom(valueClass))
				field.set(object, value);
	}
	
	
	// COPY
	@API
	public static void copyValue(Field field, Object from, Object to)
	{
		try
		{
			copyValueUncaught(field, from, to);
		}
		catch(IllegalAccessException e)
		{
			throw new ProgrammingError(e);
		}
	}
	
	@API
	public static void copyValueUncaught(Field field, Object from, Object to)
		throws IllegalAccessException
	{
		Object value = field.get(from);
		field.set(to, value);
	}
	
	
	// HELPER
	@API
	public static Set<Field> getAllFields(Object object)
	{
		var fields = new HashSet<Field>();
		Class<?> clazz = object.getClass();
		do
		{
			fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
			clazz = clazz.getSuperclass();
		}
		while(clazz != Object.class);
		
		fields.forEach(f->f.setAccessible(true));
		return fields;
	}
	
}

@@ -235,21 +235,111 @@
 reflect.
-Field
+Constructor;%0Aimport java.lang.reflect.Field;%0Aimport java.lang.reflect.InvocationTargetException
 ;%0Aimport
@@ -1881,24 +1881,581 @@
 ue);%0A%09%7D%0A%09%0A%09%0A
+%09// INIT%0A%09@SuppressWarnings(%22unchecked%22)%0A%09@API%0A%09public static %3CT%3E T instantiateNoArgs(Class%3CT%3E clazz)%0A%09%7B%0A%09%09var constructor = clazz.getConstructors()%5B0%5D;%0A%09%09var o = instantiateObject(constructor);%0A%09%09%0A%09%09return (T) o;%0A%09%7D%0A%09%0A%09private static Object instantiateObject(Constructor%3C?%3E constructor)%0A%09%7B%0A%09%09try%0A%09%09%7B%0A%09%09%09int parameterCount = constructor.getParameterCount();%0A%09%09%09return constructor.newInstance(new Object%5BparameterCount%5D);%0A%09%09%7D%0A%09%09catch(InstantiationException%7CIllegalAccessException%7CInvocationTargetException e)%0A%09%09%7B%0A%09%09%09throw new ProgrammingError(e);%0A%09%09%7D%0A%09%7D%0A%09%0A%09%0A
 %09// HELPER%0A%09

Add ReflectionUtil#instantiateNoArgs