package protocolsupport.protocol.typeremapper.watchedentity.remapper.value;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import gnu.trove.map.TIntObjectMap;
import protocolsupport.protocol.typeremapper.watchedentity.remapper.DataWatcherDataRemapper;
import protocolsupport.protocol.utils.datawatcher.DataWatcherObject;
import protocolsupport.protocol.utils.types.NetworkEntity;

public abstract class WatchedDataIndexValueRemapper<T extends DataWatcherObject<?>> extends DataWatcherDataRemapper {

	private final int fromIndex;
	private final int toIndex;
	public WatchedDataIndexValueRemapper(int fromIndex, int toIndex) {
		this.fromIndex = fromIndex;
		this.toIndex = toIndex;
	}

	private final Class<T> typeClass = getTypeClassImpl();
	@SuppressWarnings("unchecked")
	private Class<T> getTypeClassImpl() {
		ParameterizedType ptype = (ParameterizedType) this.getClass().getGenericSuperclass();
		Type type = ptype.getActualTypeArguments()[0];
		try {
			return (Class<T>) Class.forName(type.getTypeName());
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("Unable to get generic type", e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public void remap(NetworkEntity entity, TIntObjectMap<DataWatcherObject<?>> original, TIntObjectMap<DataWatcherObject<?>> remapped) {
		getObject(original, fromIndex, typeClass).ifPresent(o -> remapped.put(toIndex, remapValue((T) o.getValue())));
	}

	public abstract DataWatcherObject<?> remapValue(T object);

}

@@ -144,16 +144,48 @@
 ct.Type;
+%0Aimport java.text.MessageFormat;
 %0A%0Aimport
@@ -1048,21 +1048,16 @@
 forName(
-type.
 getTypeN
@@ -1060,16 +1060,20 @@
 ypeName(
+type
 ));%0A%09%09%7D 
@@ -1107,16 +1107,16 @@
 on e) %7B%0A
-
 %09%09%09throw
@@ -1179,16 +1179,403 @@
 %09%09%7D%0A%09%7D%0A%0A
+%09private static String getTypeName(Type type) %7B%0A%09%09if (type instanceof Class) %7B%0A%09%09%09return ((Class%3C?%3E) type).getName();%0A%09%09%7D else if (type instanceof ParameterizedType) %7B%0A%09%09%09return getTypeName(((ParameterizedType) type).getRawType());%0A%09%09%7D else %7B%0A%09%09%09throw new IllegalArgumentException(MessageFormat.format(%22Cant extract generic type from %7B0%7D:%7B1%7D%22, type.getClass().getName(), type));%0A%09%09%7D%0A%09%7D%0A%0A
 %09@Suppre

Fix generic