package cat.nyaa.nyaacore.utils;

import net.minecraft.core.IRegistry;
import net.minecraft.network.syncher.DataWatcherObject;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityTypes;
import org.bukkit.entity.EntityType;

import java.lang.reflect.Field;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;

public class EntityUtils {
    public static AtomicInteger FAKE_ENTITY_COUNTER = new AtomicInteger(0xffcc);

    public static int getNewEntityId() {
        try {
            Field ENTITY_COUNTER = Entity.class.getDeclaredField("ENTITY_COUNTER");
            return ((AtomicInteger) ENTITY_COUNTER.get(null)).incrementAndGet();
        } catch (IllegalAccessException | NoSuchFieldException ignored) {
        }
        return -FAKE_ENTITY_COUNTER.incrementAndGet();
    }

    public static Optional<Integer> getEntityTypeId(EntityType entityType) {
        Optional<EntityTypes<?>> entityTypesOptional = EntityTypes.byString(entityType.getKey().getKey());
        return entityTypesOptional.map(IRegistry.ENTITY_TYPE::getId);
    }

    /**
     * no cache
     *
     * @param entityClass         target class
     * @param EntityDataFieldName automatic obfuscation
     * @return entityDataIdOptional
     */
    public static Optional<Integer> getEntityDataId(Class<? extends net.minecraft.world.entity.Entity> entityClass, String EntityDataFieldName) {
        Field field = null;
        try {
            field = entityClass.getDeclaredField(EntityDataFieldName);
        } catch (NoSuchFieldException ignored) {
        }
        if (field == null) {
            Optional<String> fieldName = SpigotMappingUtils.getSimpleObfuscatedFieldNameOptional(entityClass.getName().replace('.', '/'), EntityDataFieldName, null);
            if (fieldName.isPresent()) {
                try {
                    field = entityClass.getDeclaredField(fieldName.get());
                } catch (NoSuchFieldException ignored) {
                }
            }
        }
        if (field == null) return Optional.empty();
        field.trySetAccessible();
        try {
            return Optional.of(((DataWatcherObject<?>) field.get(null)).getId());
        } catch (IllegalAccessException e) {
            return Optional.empty();
        }
    }

    public static Optional<Integer> getPlayerEntityDataId(String EntityDataFieldName) {
        return getEntityDataId(net.minecraft.world.entity.player.EntityHuman.class, EntityDataFieldName);
    }
}

@@ -829,37 +829,38 @@
 ();%0A    %7D%0A%0A    p
-ublic
+rivate
  static Optional
@@ -856,36 +856,46 @@
 ic Optional%3C
-Integer
+EntityTypes%3C?%3E
 %3E get
+Nms
 EntityTypeId
@@ -892,18 +892,17 @@
 tityType
-Id
+s
 (EntityT
@@ -931,54 +931,14 @@
     
-Optional%3CEntityTypes%3C?%3E%3E entityTypesOptional =
+return
  Ent
@@ -981,24 +981,107 @@
 ).getKey());
+%0A    %7D%0A    public static Optional%3CInteger%3E getEntityTypeId(EntityType entityType) %7B
 %0A        ret
@@ -1080,25 +1080,31 @@
      return 
-e
+getNmsE
 ntityTypesOp
@@ -1101,24 +1101,28 @@
 ityTypes
-Optional
+(entityType)
 .map(IRe
@@ -1150,24 +1150,353 @@
 etId);%0A    %7D
+%0A    public static int getUpdateInterval(EntityType entityType) %7B%0A        return getNmsEntityTypes(entityType).map(EntityTypes::updateInterval).orElse(3);%0A    %7D%0A    public static int getClientTrackingRange(EntityType entityType)%7B%0A        return getNmsEntityTypes(entityType).map(EntityTypes::clientTrackingRange).orElse(5);%0A    %7D
 %0A%0A    /**%0A  

update EntityUtils