package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
import javax.annotation.Nullable;
import net.minecraft.world.SimpleContainer;
import net.minecraft.Util;
import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.BooleanOp;
import net.minecraft.world.WorldlyContainer;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.shapes.CollisionContext;
import java.util.Random;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.item.Items;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.ItemLike;
import it.unimi.dsi.fastutil.objects.Object2FloatMap;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.WorldlyContainerHolder;

public class ComposterBlock extends Block implements WorldlyContainerHolder {
    public static final IntegerProperty LEVEL;
    public static final Object2FloatMap<ItemLike> COMPOSTABLES;
    private static final VoxelShape OUTER_SHAPE;
    private static final VoxelShape[] SHAPES;
    
    public static void bootStrap() {
        ComposterBlock.COMPOSTABLES.defaultReturnValue(-1.0f);
        final float float1 = 0.3f;
        final float float2 = 0.5f;
        final float float3 = 0.65f;
        final float float4 = 0.85f;
        final float float5 = 1.0f;
        add(0.3f, Items.JUNGLE_LEAVES);
        add(0.3f, Items.OAK_LEAVES);
        add(0.3f, Items.SPRUCE_LEAVES);
        add(0.3f, Items.DARK_OAK_LEAVES);
        add(0.3f, Items.ACACIA_LEAVES);
        add(0.3f, Items.BIRCH_LEAVES);
        add(0.3f, Items.OAK_SAPLING);
        add(0.3f, Items.SPRUCE_SAPLING);
        add(0.3f, Items.BIRCH_SAPLING);
        add(0.3f, Items.JUNGLE_SAPLING);
        add(0.3f, Items.ACACIA_SAPLING);
        add(0.3f, Items.DARK_OAK_SAPLING);
        add(0.3f, Items.BEETROOT_SEEDS);
        add(0.3f, Items.DRIED_KELP);
        add(0.3f, Items.GRASS);
        add(0.3f, Items.KELP);
        add(0.3f, Items.MELON_SEEDS);
        add(0.3f, Items.PUMPKIN_SEEDS);
        add(0.3f, Items.SEAGRASS);
        add(0.3f, Items.SWEET_BERRIES);
        add(0.3f, Items.WHEAT_SEEDS);
        add(0.5f, Items.DRIED_KELP_BLOCK);
        add(0.5f, Items.TALL_GRASS);
        add(0.5f, Items.CACTUS);
        add(0.5f, Items.SUGAR_CANE);
        add(0.5f, Items.VINE);
        add(0.5f, Items.NETHER_SPROUTS);
        add(0.5f, Items.WEEPING_VINES);
        add(0.5f, Items.TWISTING_VINES);
        add(0.5f, Items.MELON_SLICE);
        add(0.65f, Items.SEA_PICKLE);
        add(0.65f, Items.LILY_PAD);
        add(0.65f, Items.PUMPKIN);
        add(0.65f, Items.CARVED_PUMPKIN);
        add(0.65f, Items.MELON);
        add(0.65f, Items.APPLE);
        add(0.65f, Items.BEETROOT);
        add(0.65f, Items.CARROT);
        add(0.65f, Items.COCOA_BEANS);
        add(0.65f, Items.POTATO);
        add(0.65f, Items.WHEAT);
        add(0.65f, Items.BROWN_MUSHROOM);
        add(0.65f, Items.RED_MUSHROOM);
        add(0.65f, Items.MUSHROOM_STEM);
        add(0.65f, Items.CRIMSON_FUNGUS);
        add(0.65f, Items.WARPED_FUNGUS);
        add(0.65f, Items.NETHER_WART);
        add(0.65f, Items.CRIMSON_ROOTS);
        add(0.65f, Items.WARPED_ROOTS);
        add(0.65f, Items.SHROOMLIGHT);
        add(0.65f, Items.DANDELION);
        add(0.65f, Items.POPPY);
        add(0.65f, Items.BLUE_ORCHID);
        add(0.65f, Items.ALLIUM);
        add(0.65f, Items.AZURE_BLUET);
        add(0.65f, Items.RED_TULIP);
        add(0.65f, Items.ORANGE_TULIP);
        add(0.65f, Items.WHITE_TULIP);
        add(0.65f, Items.PINK_TULIP);
        add(0.65f, Items.OXEYE_DAISY);
        add(0.65f, Items.CORNFLOWER);
        add(0.65f, Items.LILY_OF_THE_VALLEY);
        add(0.65f, Items.WITHER_ROSE);
        add(0.65f, Items.FERN);
        add(0.65f, Items.SUNFLOWER);
        add(0.65f, Items.LILAC);
        add(0.65f, Items.ROSE_BUSH);
        add(0.65f, Items.PEONY);
        add(0.65f, Items.LARGE_FERN);
        add(0.85f, Items.HAY_BLOCK);
        add(0.85f, Items.BROWN_MUSHROOM_BLOCK);
        add(0.85f, Items.RED_MUSHROOM_BLOCK);
        add(0.85f, Items.NETHER_WART_BLOCK);
        add(0.85f, Items.WARPED_WART_BLOCK);
        add(0.85f, Items.BREAD);
        add(0.85f, Items.BAKED_POTATO);
        add(0.85f, Items.COOKIE);
        add(1.0f, Items.CAKE);
        add(1.0f, Items.PUMPKIN_PIE);
    }
    
    private static void add(final float float1, final ItemLike bqa) {
        ComposterBlock.COMPOSTABLES.put(bqa.asItem(), float1);
    }
    
    public ComposterBlock(final Properties c) {
        super(c);
        this.registerDefaultState(((StateHolder<O, BlockState>)this.stateDefinition.any()).<Comparable, Integer>setValue((Property<Comparable>)ComposterBlock.LEVEL, 0));
    }
    
    public static void handleFill(final Level bqb, final BlockPos fu, final boolean boolean3) {
        final BlockState cfj4 = bqb.getBlockState(fu);
        bqb.playLocalSound(fu.getX(), fu.getY(), fu.getZ(), boolean3 ? SoundEvents.COMPOSTER_FILL_SUCCESS : SoundEvents.COMPOSTER_FILL, SoundSource.BLOCKS, 1.0f, 1.0f, false);
        final double double5 = cfj4.getShape(bqb, fu).max(Direction.Axis.Y, 0.5, 0.5) + 0.03125;
        final double double6 = 0.13124999403953552;
        final double double7 = 0.737500011920929;
        final Random random11 = bqb.getRandom();
        for (int integer12 = 0; integer12 < 10; ++integer12) {
            final double double8 = random11.nextGaussian() * 0.02;
            final double double9 = random11.nextGaussian() * 0.02;
            final double double10 = random11.nextGaussian() * 0.02;
            bqb.addParticle(ParticleTypes.COMPOSTER, fu.getX() + 0.13124999403953552 + 0.737500011920929 * random11.nextFloat(), fu.getY() + double5 + random11.nextFloat() * (1.0 - double5), fu.getZ() + 0.13124999403953552 + 0.737500011920929 * random11.nextFloat(), double8, double9, double10);
        }
    }
    
    @Override
    public VoxelShape getShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return ComposterBlock.SHAPES[cfj.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL)];
    }
    
    @Override
    public VoxelShape getInteractionShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu) {
        return ComposterBlock.OUTER_SHAPE;
    }
    
    @Override
    public VoxelShape getCollisionShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return ComposterBlock.SHAPES[0];
    }
    
    @Override
    public void onPlace(final BlockState cfj1, final Level bqb, final BlockPos fu, final BlockState cfj4, final boolean boolean5) {
        if (cfj1.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL) == 7) {
            bqb.getBlockTicks().scheduleTick(fu, cfj1.getBlock(), 20);
        }
    }
    
    @Override
    public InteractionResult use(final BlockState cfj, final Level bqb, final BlockPos fu, final Player bec, final InteractionHand anf, final BlockHitResult deh) {
        final int integer8 = cfj.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
        final ItemStack bki9 = bec.getItemInHand(anf);
        if (integer8 < 8 && ComposterBlock.COMPOSTABLES.containsKey(bki9.getItem())) {
            if (integer8 < 7 && !bqb.isClientSide) {
                final BlockState cfj2 = addItem(cfj, bqb, fu, bki9);
                bqb.levelEvent(1500, fu, (cfj != cfj2) ? 1 : 0);
                if (!bec.abilities.instabuild) {
                    bki9.shrink(1);
                }
            }
            return InteractionResult.sidedSuccess(bqb.isClientSide);
        }
        if (integer8 == 8) {
            extractProduce(cfj, bqb, fu);
            return InteractionResult.sidedSuccess(bqb.isClientSide);
        }
        return InteractionResult.PASS;
    }
    
    public static BlockState insertItem(final BlockState cfj, final ServerLevel zd, final ItemStack bki, final BlockPos fu) {
        final int integer5 = cfj.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
        if (integer5 < 7 && ComposterBlock.COMPOSTABLES.containsKey(bki.getItem())) {
            final BlockState cfj2 = addItem(cfj, zd, fu, bki);
            bki.shrink(1);
            zd.levelEvent(1500, fu, (cfj != cfj2) ? 1 : 0);
            return cfj2;
        }
        return cfj;
    }
    
    public static BlockState extractProduce(final BlockState cfj, final Level bqb, final BlockPos fu) {
        if (!bqb.isClientSide) {
            final float float4 = 0.7f;
            final double double5 = bqb.random.nextFloat() * 0.7f + 0.15000000596046448;
            final double double6 = bqb.random.nextFloat() * 0.7f + 0.06000000238418579 + 0.6;
            final double double7 = bqb.random.nextFloat() * 0.7f + 0.15000000596046448;
            final ItemEntity bbg11 = new ItemEntity(bqb, fu.getX() + double5, fu.getY() + double6, fu.getZ() + double7, new ItemStack(Items.BONE_MEAL));
            bbg11.setDefaultPickUpDelay();
            bqb.addFreshEntity(bbg11);
        }
        final BlockState cfj2 = empty(cfj, bqb, fu);
        bqb.playSound(null, fu, SoundEvents.COMPOSTER_EMPTY, SoundSource.BLOCKS, 1.0f, 1.0f);
        return cfj2;
    }
    
    private static BlockState empty(final BlockState cfj, final LevelAccessor bqc, final BlockPos fu) {
        final BlockState cfj2 = ((StateHolder<O, BlockState>)cfj).<Comparable, Integer>setValue((Property<Comparable>)ComposterBlock.LEVEL, 0);
        bqc.setBlock(fu, cfj2, 3);
        return cfj2;
    }
    
    private static BlockState addItem(final BlockState cfj, final LevelAccessor bqc, final BlockPos fu, final ItemStack bki) {
        final int integer5 = cfj.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
        final float float6 = ComposterBlock.COMPOSTABLES.getFloat(bki.getItem());
        if ((integer5 == 0 && float6 > 0.0f) || bqc.getRandom().nextDouble() < float6) {
            final int integer6 = integer5 + 1;
            final BlockState cfj2 = ((StateHolder<O, BlockState>)cfj).<Comparable, Integer>setValue((Property<Comparable>)ComposterBlock.LEVEL, integer6);
            bqc.setBlock(fu, cfj2, 3);
            if (integer6 == 7) {
                bqc.getBlockTicks().scheduleTick(fu, cfj.getBlock(), 20);
            }
            return cfj2;
        }
        return cfj;
    }
    
    @Override
    public void tick(final BlockState cfj, final ServerLevel zd, final BlockPos fu, final Random random) {
        if (cfj.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL) == 7) {
            zd.setBlock(fu, ((StateHolder<O, BlockState>)cfj).<Comparable>cycle((Property<Comparable>)ComposterBlock.LEVEL), 3);
            zd.playSound(null, fu, SoundEvents.COMPOSTER_READY, SoundSource.BLOCKS, 1.0f, 1.0f);
        }
    }
    
    @Override
    public boolean hasAnalogOutputSignal(final BlockState cfj) {
        return true;
    }
    
    @Override
    public int getAnalogOutputSignal(final BlockState cfj, final Level bqb, final BlockPos fu) {
        return cfj.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(ComposterBlock.LEVEL);
    }
    
    @Override
    public boolean isPathfindable(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final PathComputationType czg) {
        return false;
    }
    
    @Override
    public WorldlyContainer getContainer(final BlockState cfj, final LevelAccessor bqc, final BlockPos fu) {
        final int integer5 = cfj.<Integer>getValue((Property<Integer>)ComposterBlock.LEVEL);
        if (integer5 == 8) {
            return new OutputContainer(cfj, bqc, fu, new ItemStack(Items.BONE_MEAL));
        }
        if (integer5 < 7) {
            return new InputContainer(cfj, bqc, fu);
        }
        return new EmptyContainer();
    }
    
    static {
        LEVEL = BlockStateProperties.LEVEL_COMPOSTER;
        COMPOSTABLES = (Object2FloatMap)new Object2FloatOpenHashMap();
        OUTER_SHAPE = Shapes.block();
        int integer2;
        SHAPES = Util.<VoxelShape[]>make(new VoxelShape[9], arr -> {
            for (integer2 = 0; integer2 < 8; ++integer2) {
                arr[integer2] = Shapes.join(ComposterBlock.OUTER_SHAPE, Block.box(2.0, Math.max(2, 1 + integer2 * 2), 2.0, 14.0, 16.0, 14.0), BooleanOp.ONLY_FIRST);
            }
            arr[8] = arr[7];
        });
    }
    
    static class EmptyContainer extends SimpleContainer implements WorldlyContainer {
        public EmptyContainer() {
            super(0);
        }
        
        @Override
        public int[] getSlotsForFace(final Direction fz) {
            return new int[0];
        }
        
        @Override
        public boolean canPlaceItemThroughFace(final int integer, final ItemStack bki, @Nullable final Direction fz) {
            return false;
        }
        
        @Override
        public boolean canTakeItemThroughFace(final int integer, final ItemStack bki, final Direction fz) {
            return false;
        }
    }
    
    static class OutputContainer extends SimpleContainer implements WorldlyContainer {
        private final BlockState state;
        private final LevelAccessor level;
        private final BlockPos pos;
        private boolean changed;
        
        public OutputContainer(final BlockState cfj, final LevelAccessor bqc, final BlockPos fu, final ItemStack bki) {
            super(bki);
            this.state = cfj;
            this.level = bqc;
            this.pos = fu;
        }
        
        @Override
        public int getMaxStackSize() {
            return 1;
        }
        
        @Override
        public int[] getSlotsForFace(final Direction fz) {
            return (fz == Direction.DOWN) ? new int[] { 0 } : new int[0];
        }
        
        @Override
        public boolean canPlaceItemThroughFace(final int integer, final ItemStack bki, @Nullable final Direction fz) {
            return false;
        }
        
        @Override
        public boolean canTakeItemThroughFace(final int integer, final ItemStack bki, final Direction fz) {
            return !this.changed && fz == Direction.DOWN && bki.getItem() == Items.BONE_MEAL;
        }
        
        @Override
        public void setChanged() {
            empty(this.state, this.level, this.pos);
            this.changed = true;
        }
    }
    
    static class InputContainer extends SimpleContainer implements WorldlyContainer {
        private final BlockState state;
        private final LevelAccessor level;
        private final BlockPos pos;
        private boolean changed;
        
        public InputContainer(final BlockState cfj, final LevelAccessor bqc, final BlockPos fu) {
            super(1);
            this.state = cfj;
            this.level = bqc;
            this.pos = fu;
        }
        
        @Override
        public int getMaxStackSize() {
            return 1;
        }
        
        @Override
        public int[] getSlotsForFace(final Direction fz) {
            return (fz == Direction.UP) ? new int[] { 0 } : new int[0];
        }
        
        @Override
        public boolean canPlaceItemThroughFace(final int integer, final ItemStack bki, @Nullable final Direction fz) {
            return !this.changed && fz == Direction.UP && ComposterBlock.COMPOSTABLES.containsKey(bki.getItem());
        }
        
        @Override
        public boolean canTakeItemThroughFace(final int integer, final ItemStack bki, final Direction fz) {
            return false;
        }
        
        @Override
        public void setChanged() {
            final ItemStack bki2 = this.getItem(0);
            if (!bki2.isEmpty()) {
                this.changed = true;
                final BlockState cfj3 = addItem(this.state, this.level, this.pos, bki2);
                this.level.levelEvent(1500, this.pos, (cfj3 != this.state) ? 1 : 0);
                this.removeItemNoUpdate(0);
            }
        }
    }
}
