package me.km;

import com.google.common.collect.ImmutableSet;
import java.util.Set;
import me.km.blocks.ModBlocks;
import me.km.blocks.cookingpot.TileEntityCookingPot;
import me.km.entities.ModEntities;
import me.km.items.ModItems;
import me.km.utils.ReflectionUtils;
import me.km.world.ModBiomeProvider;
import me.km.world.WorldManager;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityType;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.Biomes;
import net.minecraft.world.biome.provider.BiomeProviderType;
import net.minecraft.world.biome.provider.OverworldBiomeProviderSettings;
import net.minecraftforge.common.ModDimension;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class ObjectRegistry {
    @SubscribeEvent
    public static void onBlockRegistry(RegistryEvent.Register<Block> e) {
        ModBlocks.initBlocks(e.getRegistry());
    }

    @SubscribeEvent
    public static void onBlockMissing(RegistryEvent.MissingMappings<Block> e) {
        e.getMappings().stream()
                .forEach((missing) -> {
                    String key = missing.key.toString();
                    if(key.contains("cauldron")) {
                        missing.remap(ModBlocks.cookingPotCopper);
                    } else if(key.contains("campfire")) {
                        missing.remap(Blocks.CAMPFIRE);
                    } else if(key.contains("spikes")) {
                        missing.remap(ModBlocks.spikesCopper);
                    } else if(key.contains("campfire")) {
                        missing.remap(Blocks.CAMPFIRE);
                    } else if(key.contains("barrel")) {
                        missing.remap(Blocks.BARREL);
                    } else if(key.contains("poison") || key.contains("honey")) {
                        missing.remap(Blocks.WATER);
                    } else {
                        missing.remap(Blocks.STONE);
                    }
                });
    }

    @SubscribeEvent
    public static void onItemMissing(RegistryEvent.MissingMappings<Item> e) {
        e.getMappings().stream()
                .forEach((missing) -> {
                    missing.remap(Items.APPLE);
                });
    }

    @SubscribeEvent
    public static void onItemRegistry(RegistryEvent.Register<Item> e) {
        ModItems.init(e.getRegistry());
        ModBlocks.initItemBlocks(e.getRegistry());
    }

    @SubscribeEvent
    public static void onEntityTypeRegistry(RegistryEvent.Register<EntityType<?>> e) {
        ModEntities.init(e.getRegistry());
    }

    @SubscribeEvent
    public static void onTileEntityTypeRegistry(RegistryEvent.Register<TileEntityType<?>> e) {
        e.getRegistry().register(TileEntityCookingPot.COOKING_POT);
    }

    @SubscribeEvent
    public static void onModDimensionRegistry(RegistryEvent.Register<ModDimension> e) {
        e.getRegistry().register(WorldManager.MOD_DIMENSION);
    }

    public static BiomeProviderType<OverworldBiomeProviderSettings, ModBiomeProvider> DESERT_BIOME_PROVIDER;
    public static BiomeProviderType<OverworldBiomeProviderSettings, ModBiomeProvider> SNOW_BIOME_PROVIDER;

    private static BiomeProviderType createBiomeProviderType(Set<Biome> biomes, String name) {
        BiomeProviderType provider = ReflectionUtils.newBiomeProviderType((OverworldBiomeProviderSettings settings) -> {
            return new ModBiomeProvider(biomes, settings);
        }, OverworldBiomeProviderSettings::new);
        provider.setRegistryName(new ResourceLocation("km", name));
        return provider;
    }

    @SubscribeEvent
    public static void onBiomeProviderTypeRegistry(RegistryEvent.Register<BiomeProviderType<?, ?>> e) {
        DESERT_BIOME_PROVIDER = createBiomeProviderType(ImmutableSet.of(
                Biomes.DESERT, Biomes.DESERT_HILLS, Biomes.BADLANDS, Biomes.BADLANDS_PLATEAU,
                Biomes.DESERT_LAKES, Biomes.ERODED_BADLANDS, Biomes.MODIFIED_BADLANDS_PLATEAU), "desert_layered");
        SNOW_BIOME_PROVIDER = createBiomeProviderType(ImmutableSet.of(
                Biomes.FROZEN_OCEAN, Biomes.FROZEN_RIVER, Biomes.SNOWY_TUNDRA,
                Biomes.SNOWY_MOUNTAINS, Biomes.SNOWY_BEACH, Biomes.SNOWY_TAIGA,
                Biomes.SNOWY_TAIGA_HILLS, Biomes.DEEP_FROZEN_OCEAN,
                Biomes.ICE_SPIKES, Biomes.SNOWY_TAIGA_MOUNTAINS), "snow_layered");

        e.getRegistry().registerAll(DESERT_BIOME_PROVIDER, SNOW_BIOME_PROVIDER);
    }
}
