package net.minecraft.world.entity;

import net.minecraft.core.RegistryMaterials;
import net.minecraft.resources.MinecraftKey;
import net.minecraft.core.registries.BuiltInRegistries;

import com.bergerkiller.generated.net.minecraft.core.RegistryMaterialsHandle;
import com.bergerkiller.generated.net.minecraft.world.entity.EntityTypesHandle;

class EntityTypes {
    #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 (RegistryMaterialsHandle) RegistryMaterials<MinecraftKey, EntityTypes<?>> opt_getRegistry() {
  #if version >= 1.13.1
        return (RegistryMaterials) BuiltInRegistries.ENTITY_TYPE;
  #elseif version >= 1.13
        return (RegistryMaterials) EntityTypes.REGISTRY;
  #else
        return EntityTypes.b;
  #endif
    }
#else
    public static optional (RegistryMaterialsHandle) RegistryMaterials<MinecraftKey, EntityTypes<?>> 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 (EntityTypesHandle) EntityTypes fromEntityClass(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()) {
            EntityTypes type = (EntityTypes) iter.next();
            if (com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(type) == entityType) {
                return type;
            }
        }
        return null;
    }
#else
    public static optional (EntityTypesHandle) EntityTypes fromEntityClass:###(Class<?> entityType);
#endif

#if version >= 1.13

  #if version >= 1.14
    public static Class<?> getEntityClass(String internalEntityName) {
    #if version >= 1.18
        java.util.Optional opt = EntityTypes.byString(internalEntityName);
    #else
        java.util.Optional opt = EntityTypes.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) {
        EntityTypes type = EntityTypes.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()) {
            EntityTypes type = (EntityTypes) iter.next();
            if (com.bergerkiller.bukkit.common.internal.logic.EntityTypingHandler.INSTANCE.getClassFromEntityTypes(type) == entityType) {
  #if version >= 1.18
                MinecraftKey key = EntityTypes.getKey(type);
  #else
                MinecraftKey key = EntityTypes.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 = EntityTypes.REGISTRY.iterator();
  #endif
        while (iter.hasNext()) {
            EntityTypes type = (EntityTypes) 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 EntityTypes.REGISTRY.a((Object) type);
  #endif
            }
        }
        return -1;
    }

#elseif version >= 1.11

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

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

    public static int getEntityTypeId(Class<?> entityType) {
        return EntityTypes.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.EntityTypesHandle.T.opt_nameTypeMap_1_10_2.get();
        return (Class) map.get(internalEntityName);
    }

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

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

}
