package com.acethewildfire.acesbs.block;

import com.acethewildfire.acesbs.AcesBS;
import com.acethewildfire.acesbs.block.custom.*;
import com.acethewildfire.acesbs.sounds.ModSounds;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.*;
import net.minecraft.block.enums.NoteBlockInstrument;
import net.minecraft.block.piston.PistonBehavior;
import net.minecraft.component.type.TooltipDisplayComponent;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.tooltip.TooltipType;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.intprovider.UniformIntProvider;
import net.minecraft.world.BlockView;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.ToIntFunction;

public class ModBlocks {

    public static final Block RAW_ENTROPY_BLOCK = registerBlockWithTooltip("raw_entropy_block",
            properties -> new RawEntropyBlock(properties
                    .strength(3f)
                    .requiresTool()
                    .sounds(BlockSoundGroup.AMETHYST_BLOCK)),
            List.of(Text.translatable("tooltip.acesbs.entropy_block.tooltip"),
                    Text.translatable("tooltip.acesbs.entropy_block.tooltip2")));

    public static final Block STABLE_ENTROPY_BLOCK = registerBlockWithTooltip("stable_entropy_block",
            properties -> new StableEntropyBlock(properties
                    .strength(5f)
                    .luminance(new ToIntFunction<BlockState>() {
                        @Override
                        public int applyAsInt(BlockState value) {
                            return 7;
                        }
                    })
                    .requiresTool()
                    .sounds(BlockSoundGroup.LODESTONE)), List.of(Text.translatable("tooltip.acesbs.stable_entropy_block.tooltip")));



    public static final Block ENTROPY_ORE = registerBlock("entropy_ore",
            properties -> new ExperienceDroppingBlock(UniformIntProvider.create(3, 7),
                    properties
                            .strength(3.0F, 3.0F)
                            .mapColor(MapColor.STONE_GRAY)
                            .requiresTool()
                            .sounds(BlockSoundGroup.STONE)));

    public static final Block DEEPSLATE_ENTROPY_ORE = registerBlock("deepslate_entropy_ore",
            properties -> new ExperienceDroppingBlock(UniformIntProvider.create(3, 7),
                    properties
                            .mapColor(MapColor.DEEPSLATE_GRAY)
                            .strength(4.5F, 3.0F)
                            .requiresTool()
                            .sounds(BlockSoundGroup.DEEPSLATE)));

    public static final Block ENDTROPY_ORE = registerBlock("endtropy_ore",
            properties -> new ExperienceDroppingBlock(UniformIntProvider.create(3, 7),
                   properties
                           .mapColor(MapColor.PALE_YELLOW)
                           .requiresTool()
                           .strength(3.0F, 9.0F)));

    public static final Block RAW_ENDTROPY_BLOCK = registerBlockWithTooltip("raw_endtropy_block",
            properties -> new RawEndtropyBlock(properties
                    .strength(3f)
                    .requiresTool()
                    .sounds(BlockSoundGroup.AMETHYST_BLOCK)),
            List.of(Text.translatable("tooltip.acesbs.endtropy_block.tooltip")));

    public static final Block STABLE_ENDTROPY_BLOCK = registerBlockWithTooltip("stable_endtropy_block",
            properties -> new StableEndtropyBlock(properties
                    .strength(3f)
                    .requiresTool()
                    .sounds(BlockSoundGroup.AMETHYST_BLOCK)), List.of(Text.translatable("tooltip.acesbs.stable_endtropy_block.tooltip")));

    public static final Block INFERNAL_ASHES_ORE = registerBlock("infernal_ashes_ore",
            properties -> new ExperienceDroppingBlock(
                    UniformIntProvider.create(0, 1),
                    properties
                            .mapColor(MapColor.DARK_RED)
                            .requiresTool()
                            .strength(3.0F, 3.0F)
                            .sounds(BlockSoundGroup.NETHER_GOLD_ORE)));

    public static final Block ENTROPIC_STABILIZER = registerBlock("entropic_stabilizer",
            properties -> new EntropicStabilizer(
                    properties
                            .mapColor(MapColor.LIGHT_GRAY)
                            .strength(2.0F, 3.0F)
                            .sounds(BlockSoundGroup.METAL)
                            .requiresTool()
            ));

    public static final Block ENTROPIC_EVISCERATOR = registerBlock("entropic_eviscerator",
            properties -> new EntropicEviscerator(
                    properties
                            .mapColor(MapColor.LIGHT_GRAY)
                            .strength(2.0F, 3.0F)
                            .sounds(BlockSoundGroup.METAL)
                            .requiresTool()
            ));
    public static final Block ENTROPIC_ENTANGLER = registerBlock("entropic_entangler",
            properties -> new EntropicEntangler(
                    properties
                            .mapColor(MapColor.LIGHT_GRAY)
                            .strength(2.0F, 3.0F)
                            .sounds(BlockSoundGroup.METAL)
                            .requiresTool()
            ));

    public static final Block ORDERED_CORE = registerBlock("ordered_core",
            properties -> new HeavyCoreBlock(
                    properties
                            .mapColor(MapColor.IRON_GRAY)
                            .instrument(NoteBlockInstrument.SNARE)
                            .sounds(BlockSoundGroup.HEAVY_CORE)
                            .strength(10.0F)
                            .pistonBehavior(PistonBehavior.NORMAL)
                            .resistance(1200.0F)
            ));


    public static final Block LIZARD_PLANKS = registerBlock("lizard_planks",
            properties -> new Block(
                    properties
                            .mapColor(MapColor.DARK_GREEN)
                            .strength(2.0F, 3.0F)
                            .sounds(BlockSoundGroup.WOOD)
                            .burnable()
            ));

    public static final Block LIZARD_BUTTON = registerBlock("lizard_button",
            properties -> new ButtonBlock(BlockSetType.BIRCH, 1,
                   properties
                            .mapColor(MapColor.DARK_GREEN)
                            .strength(2.0F, 3.0F)
                            .sounds(BlockSoundGroup.WOOD)
                            .burnable()
                            .noCollision()
            ){
                private final BlockSetType blockSetType = BlockSetType.BIRCH;

//                @Override
//                protected void playClickSound(@Nullable PlayerEntity player, WorldAccess world, BlockPos pos, boolean powered) {
//                    world.playSound(powered ? player : null, pos, ModSounds.LIZARD, SoundCategory.BLOCKS);
//                }
                @Override
                protected SoundEvent getClickSound(boolean powered) {
                    return powered ? ModSounds.LIZARD : this.blockSetType.buttonClickOff();
                }
            });

    public static final Block EVIL_BLOCK = registerBlock("evil_block",
            properties -> new EvilBlock(properties
                    .strength(5f)
                    .luminance(state -> state.get(EvilBlock.CLICKED) ? 15 : 0)
                    .requiresTool()
                    .sounds(BlockSoundGroup.LODESTONE)));

    public static final Block PRISMA_STEEL_BLOCK = registerBlock(
    "prisma_steel_block",
            properties -> new Block(
            properties
				.mapColor(MapColor.IRON_GRAY)
				.instrument(NoteBlockInstrument.IRON_XYLOPHONE)
				.requiresTool()
				.strength(5.0F, 6.0F)
				.sounds(BlockSoundGroup.METAL)
		)
    );

    public static final Block ASHEN_STEEL_BLOCK = registerBlock(
            "ashen_steel_block",
            properties -> new Block(
                    properties
                            .mapColor(MapColor.IRON_GRAY)
                            .instrument(NoteBlockInstrument.IRON_XYLOPHONE)
                            .requiresTool()
                            .strength(5.0F, 6.0F)
                            .sounds(BlockSoundGroup.METAL)
            )
    );

    public static final Block FRACTAL_DIAMOND_BLOCK = registerBlock(
            "fractal_diamond_block",
            properties -> new Block(
                    properties
                            .mapColor(MapColor.WHITE_GRAY)
                            .instrument(NoteBlockInstrument.CHIME)
                            .requiresTool()
                            .strength(5.0F, 6.0F)
                            .sounds(BlockSoundGroup.METAL)
            )
    );

    public static final Block HELLFIRE_DIAMOND_BLOCK = registerBlock(
            "hellfire_diamond_block",
            properties -> new Block(
                    properties
                            .mapColor(MapColor.DULL_RED)
                            .instrument(NoteBlockInstrument.CHIME)
                            .requiresTool()
                            .strength(5.0F, 6.0F)
                            .sounds(BlockSoundGroup.METAL)
            )
    );

    public static final Block INFERNAL_ASHES_BLOCK = registerBlock(
            "infernal_ashes_block",
            properties -> new FallingBlock(
                    properties
                            .mapColor(MapColor.LIGHT_GRAY)
                            .instrument(NoteBlockInstrument.SNARE)
                            .strength(0.5F)
                            .sounds(BlockSoundGroup.SAND)
            ) {
                @Override
                protected MapCodec<? extends FallingBlock> getCodec() {
                    return null;
                }

                @Override
                public int getColor(BlockState state, BlockView world, BlockPos pos) {
                    return 0;
                }
            }
    );

    public static final Block CRYSTAL_ENTROPY = registerBlock(
            "crystal_entropy",
            properties -> new TransparentBlock(
                    properties
                            .instrument(NoteBlockInstrument.HAT)
                            .strength(0.3F)
                            .sounds(BlockSoundGroup.GLASS)
                            .nonOpaque()
                            .allowsSpawning(Blocks::never)
                            .solidBlock(Blocks::never)
                            .suffocates(Blocks::never)
                            .blockVision(Blocks::never)
            )
    );

    public static final Block CRYSTAL_ENTROPY_PANE = registerBlock(
            "crystal_entropy_pane",
            properties -> new PaneBlock(
                    properties
                            .instrument(NoteBlockInstrument.HAT)
                            .strength(0.3F)
                            .sounds(BlockSoundGroup.GLASS)
                            .nonOpaque()
            )
    );

    public static final Block TOBACCO_CROP = registerBlockWithoutItem("tobacco_crop", properties -> new TobaccoCrop(
            properties
                    .mapColor(MapColor.DARK_GREEN)
                    .noCollision()
                    .ticksRandomly()
                    .breakInstantly()
                    .sounds(BlockSoundGroup.CROP)
                    .pistonBehavior(PistonBehavior.DESTROY)
    ));

    public static Block registerBlock(String name, Function<AbstractBlock.Settings, Block> function) {
        Block toRegister = function.apply(AbstractBlock.Settings.create().registryKey(RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(AcesBS.MOD_ID, name))));
        registerBlockItem(name, toRegister);
        return Registry.register(Registries.BLOCK, Identifier.of(AcesBS.MOD_ID, name), toRegister);
    }

    //Fuck you Devs for making it so blocks no longer have appendTooltip, makes shit much harder when I have to separately manage BlockItems.
    private static Block registerBlockWithTooltip(String name, Function<AbstractBlock.Settings, Block> function, List<Text> texts) {
        Block toRegister = function.apply(AbstractBlock.Settings.create().registryKey(RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(AcesBS.MOD_ID, name))));
        registerBlockItemWithTootip(name, toRegister, texts);
        return Registry.register(Registries.BLOCK, Identifier.of(AcesBS.MOD_ID, name), toRegister);
    }

    private static Block registerBlockWithoutItem(String name, Function<AbstractBlock.Settings, Block> function) {
        return Registry.register(Registries.BLOCK, Identifier.of(AcesBS.MOD_ID, name),
                function.apply(AbstractBlock.Settings.create().registryKey(RegistryKey.of(RegistryKeys.BLOCK, Identifier.of(AcesBS.MOD_ID, name)))));
    }

    private static void registerBlockItem(String name, Block block) {
        Registry.register(Registries.ITEM, Identifier.of(AcesBS.MOD_ID, name),
                new BlockItem(block, new Item.Settings().useBlockPrefixedTranslationKey()
                        .registryKey(RegistryKey.of(RegistryKeys.ITEM, Identifier.of(AcesBS.MOD_ID, name)))));
    }

    private static void registerBlockItemWithTootip(String name, Block block, List<Text> texts) {
        Registry.register(Registries.ITEM, Identifier.of(AcesBS.MOD_ID, name),
                new BlockItem(block, new Item.Settings().useBlockPrefixedTranslationKey()
                        .registryKey(RegistryKey.of(RegistryKeys.ITEM, Identifier.of(AcesBS.MOD_ID, name)))){
                    @Override
                    public void appendTooltip(ItemStack stack, TooltipContext context, TooltipDisplayComponent displayComponent, Consumer<Text> textConsumer, TooltipType type) {
                        for (Text text : texts){
                            textConsumer.accept(text);
                        }
                        super.appendTooltip(stack, context, displayComponent, textConsumer, type);

                    }
                });
    }

    public static void registerModBlocks(){
        AcesBS.LOGGER.info("Registering Mod Blocks for " + AcesBS.MOD_ID);
        LemonWoodBlocks.registerLemonwoodBlocks();
        FireOakBlocks.registerFireOakBlocks();

//        ItemGroupEvents.modifyEntriesEvent(ItemGroups.BUILDING_BLOCKS).register(fabricItemGroupEntries -> {
//            fabricItemGroupEntries.add(ENTROPY_BLOCK);
//        });
    }
}
