package net.minecraft.world.entity;

import net.minecraft.core.MappedRegistry;
import net.minecraft.resources.Identifier;
import net.minecraft.core.registries.BuiltInRegistries;

import com.bergerkiller.generated.net.minecraft.core.MappedRegistryHandle;
import com.bergerkiller.generated.net.minecraft.world.entity.EntityTypeHandle;

class EntityType {
    #bootstrap com.bergerkiller.bukkit.common.internal.CommonBootstrap.initServer();

    // 1.10.2 and before used a Map<String, Class> and Map<Class, String> to store name to entity class information
#if version >= 1.11
    private static optional final (Map<String, Class<?>>) Map<String, Class<? extends Entity>> opt_nameTypeMap_1_10_2:###;
    private static optional final (Map<Class<?>, String>) Map<Class<? extends Entity>, String> opt_typeNameMap_1_10_2:###;
#else
    private static optional final (Map<String, Class<?>>) Map<String, Class<? extends Entity>> opt_nameTypeMap_1_10_2:c;
    private static optional final (Map<Class<?>, String>) Map<Class<? extends Entity>, String> opt_typeNameMap_1_10_2:d;
#endif

    // Between MC 1.11 and 1.12.2 inclusively, this is used to find the 'name' of an entity by type id
#if version >= 1.11
  #if version <= 1.12.2
    private static optional final List<String> opt_typeIdToName_1_11:g;
  #else
    private static optional final List<String> opt_typeIdToName_1_11:###;
  #endif
#else
    private static optional final List<String> opt_typeIdToName_1_11:###;
#endif

#if version >= 1.11
    private static optional final (Map<Class<?>, Integer>) Map<Class<? extends Entity>, Integer> opt_typeIdMap_1_8:###;
#elseif version >= 1.8.3
    private static optional final (Map<Class<?>, Integer>) Map<Class<? extends Entity>, Integer> opt_typeIdMap_1_8:f;
#else
    private static optional final (Map<Class<?>, Integer>) Map opt_typeIdMap_1_8:f;
#endif

#if version >= 1.11
    public static optional (MappedRegistryHandle) MappedRegistry<EntityType<?>> opt_getRegistry() {
  #if version >= 1.13.1
        return (MappedRegistry) BuiltInRegistries.ENTITY_TYPE;
  #elseif version >= 1.13
        return (MappedRegistry) EntityType.REGISTRY;
  #else
        return EntityType.b;
  #endif
    }
#else
    public static optional (MappedRegistryHandle) MappedRegistry<EntityType<?>> opt_getRegistry:###();
#endif

#if version >= 1.14
    public optional (Class<?>) Class<? extends Entity> getEntityClassInst() {
        return com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(instance);
    }

    public optional int getTypeId() {
  #if version >= 1.17
        return BuiltInRegistries.ENTITY_TYPE.getId((Object) instance);
  #else
        return BuiltInRegistries.ENTITY_TYPE.a((Object) instance);
  #endif
    }
#elseif version >= 1.13
    public optional (Class<?>) Class<? extends Entity> getEntityClassInst:c();
    public optional int getTypeId:###();
#else
    public optional (Class<?>) Class<? extends Entity> getEntityClassInst:###();
    public optional int getTypeId:###();
#endif

#if version >= 1.13
    public static optional (EntityTypeHandle) EntityType fromEntityClass(Class<?> entityType) {
#if version >= 1.13.1
        java.util.Iterator iter = BuiltInRegistries.ENTITY_TYPE.iterator();
#else
        java.util.Iterator iter = EntityType.REGISTRY.iterator();
#endif
        while (iter.hasNext()) {
            EntityType type = (EntityType) iter.next();
            if (com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(type) == entityType) {
                return type;
            }
        }
        return null;
    }
#else
    public static optional (EntityTypeHandle) EntityType fromEntityClass:###(Class<?> entityType);
#endif

#if version >= 1.13

  #if version >= 1.14
    public static Class<?> getEntityClass(String internalEntityName) {
    #if version >= 26.2
        java.util.Optional opt = BuiltInRegistries.ENTITY_TYPE.getOptional(Identifier.tryParse(internalEntityName));
    #elseif version >= 1.18
        java.util.Optional opt = EntityType.byString(internalEntityName);
    #else
        java.util.Optional opt = EntityType.a(internalEntityName);
    #endif
        if (opt.isPresent()) {
            return com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(opt.get());
        } else {
            return null;
        }
    }
  #else
    public static Class<?> getEntityClass(String internalEntityName) {
        EntityType type = EntityType.a(internalEntityName);
        if (type == null) {
            return null;
        } else {
            return com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(type);
        }
    }
  #endif

    public static String getEntityInternalName(Class<?> entityType) {
  #if version >= 1.13.1
        java.util.Iterator iter = BuiltInRegistries.ENTITY_TYPE.iterator();
  #else
        java.util.Iterator iter = EntityTypes.REGISTRY.iterator();
  #endif
        while (iter.hasNext()) {
            EntityType type = (EntityType) iter.next();
            if (com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(type) == entityType) {
  #if version >= 1.18
                Identifier key = EntityType.getKey(type);
  #else
                Identifier key = EntityType.getName(type);
  #endif
                if (key != null) {
                    return key.toString();
                }
            }
        }
        return null;
    }

    public static int getEntityTypeId(Class<?> entityType) {
  #if version >= 1.13.1
        java.util.Iterator iter = BuiltInRegistries.ENTITY_TYPE.iterator();
  #else
        java.util.Iterator iter = EntityType.REGISTRY.iterator();
  #endif
        while (iter.hasNext()) {
            EntityType type = (EntityType) iter.next();
            if (com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(type) == entityType) {
  #if version >= 1.17
                return BuiltInRegistries.ENTITY_TYPE.getId((Object) type);
  #elseif version >= 1.13.1
                return BuiltInRegistries.ENTITY_TYPE.a((Object) type);
  #else
                return EntityType.REGISTRY.a((Object) type);
  #endif
            }
        }
        return -1;
    }

#elseif version >= 1.11

    public static Class<?> getEntityClass(String internalEntityName) {
        return (Class) EntityType.b.get((Object) new Identifier(internalEntityName));
    }

    public static String getEntityInternalName(Class<?> entityType) {
        Identifier key = EntityType.getName(entityType);
        if (key == null) {
            return null;
        } else {
            return key.toString();
        }
    }

    public static int getEntityTypeId(Class<?> entityType) {
        return EntityType.b.a((Object) entityType);
    }

#elseif version >= 1.9

    public static Class<?> getEntityClass(String internalEntityName) {
        java.util.Map map = com.bergerkiller.generated.net.minecraft.world.entity.EntityTypeHandle.T.opt_nameTypeMap_1_10_2.get();
        return (Class) map.get(internalEntityName);
    }

    public static String getEntityInternalName(Class<?> entityType) {
        return EntityType.getName(entityType);
    }

    public static int getEntityTypeId(Class<?> entityType) {
        java.util.Map map = com.bergerkiller.generated.net.minecraft.world.entity.EntityTypeHandle.T.opt_typeIdMap_1_8.get();
        Integer id = (Integer) map.get(entityType);
        if (id != null) {
            return id.intValue();
        } else {
            return -1;
        }
    }

#else

    public static Class<?> getEntityClass(String internalEntityName) {
        java.util.Map map = com.bergerkiller.generated.net.minecraft.world.entity.EntityTypeHandle.T.opt_nameTypeMap_1_10_2.get();
        return (Class) map.get(internalEntityName);
    }

    public static String getEntityInternalName(Class<?> entityType) {
        java.util.Map map = com.bergerkiller.generated.net.minecraft.world.entity.EntityTypeHandle.T.opt_typeNameMap_1_10_2.get();
        return (String) map.get(entityType);
    }

    public static int getEntityTypeId(Class<?> entityType) {
        java.util.Map map = com.bergerkiller.generated.net.minecraft.world.entity.EntityTypeHandle.T.opt_typeIdMap_1_8.get();
        Integer id = (Integer) map.get(entityType);
        if (id != null) {
            return id.intValue();
        } else {
            return -1;
        }
    }
#endif

}
