package org.cyclops.cyclopscore.config.extendedconfig;

import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.EntityRenderers;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.item.Item;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.ForgeSpawnEggItem;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.IForgeRegistry;
import org.cyclops.cyclopscore.config.ConfigurableType;
import org.cyclops.cyclopscore.init.ModBase;

import javax.annotation.Nullable;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 * Config for entities.
 * @param <T> The entity type
 * @author rubensworks
 * @see ExtendedConfig
 */
public abstract class EntityConfig<T extends Entity> extends ExtendedConfigForge<EntityConfig<T>, EntityType<T>> {

    @Nullable
    private ItemConfig spawnEggItemConfig;

    public EntityConfig(ModBase mod, String namedId, Function<EntityConfig<T>, EntityType.Builder<T>> elementConstructor) {
        this(mod, namedId, elementConstructor, null);
    }

    public EntityConfig(ModBase mod, String namedId, Function<EntityConfig<T>, EntityType.Builder<T>> elementConstructor,
                        @Nullable BiFunction<EntityConfig<T>, EntityType<T>, ItemConfig> spawnEggItemConstructor) {
        super(mod, namedId, elementConstructor
                .andThen(builder -> builder.build(mod.getModId() + ":" + namedId)));

        // Register spawn egg if applicable
        if (spawnEggItemConstructor != null) {
            mod.getConfigHandler().addConfigurable(spawnEggItemConstructor.apply(this, getInstance()));
        }
    }

    public static <T extends Mob> BiFunction<EntityConfig<T>, EntityType<T>, ItemConfig> getDefaultSpawnEggItemConfigConstructor(ModBase mod, String itemName, int primaryColorIn, int secondaryColorIn) {
        return getDefaultSpawnEggItemConfigConstructor(mod, itemName, primaryColorIn, secondaryColorIn, null);
    }

    public static <T extends Mob> BiFunction<EntityConfig<T>, EntityType<T>, ItemConfig> getDefaultSpawnEggItemConfigConstructor(ModBase mod, String itemName, int primaryColorIn, int secondaryColorIn, @Nullable Function<Item.Properties, Item.Properties> itemPropertiesModifier) {
        return (entityConfig, entityType) -> {
            Item.Properties itemProperties = new Item.Properties().tab(mod.getDefaultItemGroup());
            if (itemPropertiesModifier != null) {
                itemProperties = itemPropertiesModifier.apply(itemProperties);
            }
            Item.Properties finalItemProperties = itemProperties;
            ItemConfig itemConfig = new ItemConfig(mod, itemName, (itemConfigSub) -> new ForgeSpawnEggItem(() -> entityType, primaryColorIn, secondaryColorIn, finalItemProperties));
            entityConfig.setSpawnEggItemConfig(itemConfig);
            return itemConfig;
        };
    }

    @Override
    public String getTranslationKey() {
        return "entity." + getNamedId();
    }

    @Override
    public ConfigurableType getConfigurableType() {
        return ConfigurableType.ENTITY;
    }

    @Override
    @OnlyIn(Dist.CLIENT)
    public void onRegistered() {
        super.onRegistered();
        EntityRenderers.register(getInstance(),
                manager -> EntityConfig.this.getRender(manager, Minecraft.getInstance().getItemRenderer()));

    }

    /**
     * Get the render for this configurable.
     * @param renderContext The render context.
     * @param renderItem The render item instance.
     * @return Get the render.
     */
    @OnlyIn(Dist.CLIENT)
    public abstract EntityRenderer<? super T> getRender(EntityRendererProvider.Context renderContext, ItemRenderer renderItem);

    @Override
    public IForgeRegistry<EntityType<?>> getRegistry() {
        return ForgeRegistries.ENTITIES;
    }

    @Nullable
    public ItemConfig getSpawnEggItemConfig() {
        return spawnEggItemConfig;
    }

    public void setSpawnEggItemConfig(@Nullable ItemConfig spawnEggItemConfig) {
        this.spawnEggItemConfig = spawnEggItemConfig;
    }
}

@@ -964,16 +964,52 @@
 unction;
+%0Aimport java.util.function.Supplier;
 %0A%0A/**%0A *
@@ -1645,32 +1645,41 @@
 ntityConfig%3CT%3E, 
+Supplier%3C
 EntityType%3CT%3E, I
@@ -1667,32 +1667,33 @@
 er%3CEntityType%3CT%3E
+%3E
 , ItemConfig%3E sp
@@ -2028,16 +2028,22 @@
 y(this, 
+this::
 getInsta
@@ -2045,18 +2045,16 @@
 Instance
-()
 ));%0A    
@@ -2120,32 +2120,41 @@
 ntityConfig%3CT%3E, 
+Supplier%3C
 EntityType%3CT%3E, I
@@ -2142,32 +2142,33 @@
 er%3CEntityType%3CT%3E
+%3E
 , ItemConfig%3E ge
@@ -2451,32 +2451,41 @@
 ntityConfig%3CT%3E, 
+Supplier%3C
 EntityType%3CT%3E, I
@@ -2481,16 +2481,17 @@
 yType%3CT%3E
+%3E
 , ItemCo
@@ -3153,14 +3153,8 @@
 tem(
-() -%3E 
 enti

Fix entity registrations crashing in 1.18.2