package protocolsupport.zplatform.impl.spigot.injector;

import java.lang.reflect.Field;
import java.util.logging.Level;

import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;

import net.minecraft.server.v1_14_R1.PlayerChunkMap;
import protocolsupport.ProtocolSupport;
import protocolsupport.utils.ReflectionUtils;
import protocolsupport.zplatform.impl.spigot.entitytracker.PaperSpigotEntityTrackerEntryInjectorMap;
import protocolsupport.zplatform.impl.spigot.entitytracker.SpigotEntityTrackerEntryInjectorMap;

public class SpigotEntityTrackerInjector implements Listener {

	protected final Field field;
	protected final Object injectorMap;
	public SpigotEntityTrackerInjector() {
		Field lField = null;
		Object lInjectorMap = null;
		try {
			lField = ReflectionUtils.getField(PlayerChunkMap.class, "trackedEntities");
			switch (lField.getType().getName()) {
				case "org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.ints.Int2ObjectMap": {
					lInjectorMap = new SpigotEntityTrackerEntryInjectorMap();
					break;
				}
				case "it.unimi.dsi.fastutil.ints.Int2ObjectMap": {
					lInjectorMap = new PaperSpigotEntityTrackerEntryInjectorMap();
					break;
				}
				default: {
					throw new IllegalArgumentException("Can't find an entity tracker injector map for type " + lField.getType().getName());
				}
			}
		} catch (Throwable e) {
			ProtocolSupport.getInstance().getLogger().log(Level.SEVERE, e, () -> "Failed to create entity tracker entry injector");
		}
		this.field = lField;
		this.injectorMap = lInjectorMap;
	}

	@EventHandler
	public void onWorldInit(WorldInitEvent event) {
		if (injectorMap == null) {
			return;
		}
		PlayerChunkMap chunkmap = ((CraftWorld) event.getWorld()).getHandle().getChunkProvider().playerChunkMap;
		try {
			field.set(chunkmap, injectorMap);
		} catch (IllegalArgumentException | IllegalAccessException e) {
			ProtocolSupport.getInstance().getLogger().log(Level.SEVERE, e, () -> "Failed to inject entity tracker entry injector");
		}
	}

}

@@ -78,24 +78,60 @@
 lect.Field;%0A
+import java.util.function.Supplier;%0A
 import java.
@@ -150,16 +150,16 @@
 .Level;%0A
-
 %0Aimport 
@@ -769,22 +769,32 @@
 d final 
+Supplier%3C
 Object
+%3E
  injecto
@@ -797,16 +797,24 @@
 ectorMap
+Supplier
 ;%0A%09publi
@@ -872,22 +872,32 @@
 null;%0A%09%09
+Supplier%3C
 Object
+%3E
  lInject
@@ -897,24 +897,32 @@
 lInjectorMap
+Supplier
  = null;%0A%09%09t
@@ -1146,22 +1146,26 @@
 ectorMap
- = new
+Supplier =
  SpigotE
@@ -1184,34 +1184,37 @@
 EntryInjectorMap
-()
+::new
 ;%0A%09%09%09%09%09break;%0A%09%09
@@ -1293,14 +1293,18 @@
 rMap
- = new
+Supplier =
  Pap
@@ -1340,18 +1340,21 @@
 ectorMap
-()
+::new
 ;%0A%09%09%09%09%09b
@@ -1710,16 +1710,24 @@
 ectorMap
+Supplier
  = lInje
@@ -1733,16 +1733,24 @@
 ectorMap
+Supplier
 ;%0A%09%7D%0A%0A%09@
@@ -1828,16 +1828,24 @@
 ectorMap
+Supplier
  == null
@@ -1978,16 +1978,16 @@
 %09%09try %7B%0A
-
 %09%09%09field
@@ -2012,16 +2012,30 @@
 ectorMap
+Supplier.get()
 );%0A%09%09%7D c

Fix using the same instance of entity tracker injector map in all worlds.