package org.cyclops.cyclopscore.config.configurabletypeaction;

import com.google.common.collect.Lists;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.color.IBlockColor;
import net.minecraft.client.renderer.model.IBakedModel;
import net.minecraft.client.renderer.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ForgeRegistries;
import org.apache.commons.lang3.tuple.Pair;
import org.cyclops.cyclopscore.client.model.IDynamicModelElement;
import org.cyclops.cyclopscore.config.extendedconfig.BlockConfig;
import org.cyclops.cyclopscore.helper.MinecraftHelpers;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.function.BiFunction;

/**
 * The action used for {@link BlockConfig}.
 * @author rubensworks
 * @see ConfigurableTypeAction
 */
public class BlockAction extends ConfigurableTypeActionForge<BlockConfig, Block> {

    private static final List<BlockConfig> MODEL_ENTRIES = Lists.newArrayList();

    static {
        if (MinecraftHelpers.isClientSide()) {
            FMLJavaModLoadingContext.get().getModEventBus().addListener(BlockAction::onModelRegistryLoad);
            FMLJavaModLoadingContext.get().getModEventBus().addListener(BlockAction::onModelBakeEvent);
        }
    }

    /**
     * Registers a block and its optional item block.
     * @param itemBlockConstructor The optional item block constructor.
     * @param config The config.
     * @param callback A callback that will be called when the entry is registered.
     */
    public static void register(@Nullable BiFunction<BlockConfig, Block, ? extends Item> itemBlockConstructor, BlockConfig config, @Nullable Callable<?> callback) {
        register(config, itemBlockConstructor == null ? callback : null); // Delay onForgeRegistered callback until item has been registered if one is applicable
        if(itemBlockConstructor != null) {
            FMLJavaModLoadingContext.get().getModEventBus().addListener((RegistryEvent.Register<Item> event) -> {
                if (event.getRegistry() == ForgeRegistries.ITEMS) {
                    Item itemBlock = itemBlockConstructor.apply(config, config.getInstance());
                    Objects.requireNonNull(itemBlock, "Received a null item for the item block constructor of " + config.getNamedId());
                    if (itemBlock.getRegistryName() == null) {
                        itemBlock.setRegistryName(new ResourceLocation(config.getMod().getModId(), config.getNamedId()));
                    }
                    event.getRegistry().register(itemBlock);
                    config.setItemInstance(itemBlock);
                    try {
                        if (callback != null) {
                            callback.call();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    @Override
    public void onRegisterForge(BlockConfig eConfig) {
        // Register block and set creative tab.
        register(eConfig.getItemConstructor(), eConfig, () -> {
            eConfig.onForgeRegistered(); // Manually call after item has been registered
            this.polish(eConfig);
            return null;
        });
    }

    @OnlyIn(Dist.CLIENT)
    public static void onModelRegistryLoad(ModelRegistryEvent event) {
        for (BlockConfig config : MODEL_ENTRIES) {
            Pair<ModelResourceLocation, ModelResourceLocation> resourceLocations = config.registerDynamicModel();
            config.dynamicBlockVariantLocation = resourceLocations.getLeft();
            config.dynamicItemVariantLocation  = resourceLocations.getRight();
        }
    }

    @OnlyIn(Dist.CLIENT)
    public static void onModelBakeEvent(ModelBakeEvent event){
        for (BlockConfig config : MODEL_ENTRIES) {
            IDynamicModelElement dynamicModelElement = (IDynamicModelElement) config.getInstance();
            IBakedModel dynamicModel = dynamicModelElement.createDynamicModel(event);
            event.getModelRegistry().put(config.dynamicBlockVariantLocation, dynamicModel);
            event.getModelRegistry().put(config.dynamicItemVariantLocation, dynamicModel);
        }
    }

    public static void handleDynamicBlockModel(BlockConfig extendedConfig) {
        MODEL_ENTRIES.add(extendedConfig);
    }

    protected void polish(BlockConfig config) {
        Block block = config.getInstance();
        if(MinecraftHelpers.isClientSide()) {
            IBlockColor blockColorHandler = config.getBlockColorHandler();
            if (blockColorHandler != null) {
                Minecraft.getInstance().getBlockColors().register(blockColorHandler, block);
            }
        }
    }
}

@@ -2439,32 +2439,39 @@
 odEventBus().add
+Generic
 Listener((Regist
@@ -2463,16 +2463,28 @@
 istener(
+Item.class, 
 (Registr
@@ -2521,80 +2521,8 @@
 %3E %7B%0A
-                if (event.getRegistry() == ForgeRegistries.ITEMS) %7B%0A    
     
@@ -2604,28 +2604,24 @@
 nstance());%0A
-    
             
@@ -2752,28 +2752,24 @@
             
-    
 if (itemBloc
@@ -2819,20 +2819,16 @@
         
-  
-  
 itemBloc
@@ -2929,34 +2929,26 @@
             
-    %7D%0A    
+%7D%0A
             
@@ -3004,28 +3004,24 @@
             
-    
 config.setIt
@@ -3059,20 +3059,16 @@
         
-    
 try %7B%0A  
@@ -3081,28 +3081,24 @@
             
-  
-  
 if (callback
@@ -3133,20 +3133,16 @@
         
-    
 callback
@@ -3146,28 +3146,24 @@
 ack.call();%0A
-    
             
@@ -3188,20 +3188,16 @@
         
-    
 %7D catch 
@@ -3232,20 +3232,16 @@
         
-    
 e.printS
@@ -3253,38 +3253,16 @@
 race();%0A
-                    %7D%0A
         

Fix blocks not being able to register