package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.AbstractStateHolder;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.level.block.state.StateDefinition;
import java.util.Iterator;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.Level;
import java.util.Random;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.level.block.piston.MovingPistonBlock;
import net.minecraft.world.level.LevelReader;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.properties.IntegerProperty;

public class FarmBlock extends Block {
    public static final IntegerProperty MOISTURE;
    protected static final VoxelShape SHAPE;
    
    protected FarmBlock(final Properties c) {
        super(c);
        this.registerDefaultState(((AbstractStateHolder<O, BlockState>)this.stateDefinition.any()).<Comparable, Integer>setValue((Property<Comparable>)FarmBlock.MOISTURE, 0));
    }
    
    @Override
    public BlockState updateShape(final BlockState byj1, final Direction fp, final BlockState byj3, final LevelAccessor bjx, final BlockPos fk5, final BlockPos fk6) {
        if (fp == Direction.UP && !byj1.canSurvive(bjx, fk5)) {
            bjx.getBlockTicks().scheduleTick(fk5, this, 1);
        }
        return super.updateShape(byj1, fp, byj3, bjx, fk5, fk6);
    }
    
    @Override
    public boolean canSurvive(final BlockState byj, final LevelReader bjz, final BlockPos fk) {
        final BlockState byj2 = bjz.getBlockState(fk.above());
        return !byj2.getMaterial().isSolid() || byj2.getBlock() instanceof FenceGateBlock || byj2.getBlock() instanceof MovingPistonBlock;
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bcq) {
        if (!this.defaultBlockState().canSurvive(bcq.getLevel(), bcq.getClickedPos())) {
            return Blocks.DIRT.defaultBlockState();
        }
        return super.getStateForPlacement(bcq);
    }
    
    @Override
    public boolean useShapeForLightOcclusion(final BlockState byj) {
        return true;
    }
    
    @Override
    public VoxelShape getShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        return FarmBlock.SHAPE;
    }
    
    @Override
    public void tick(final BlockState byj, final ServerLevel xd, final BlockPos fk, final Random random) {
        if (!byj.canSurvive(xd, fk)) {
            turnToDirt(byj, xd, fk);
            return;
        }
        final int integer6 = byj.<Integer>getValue((Property<Integer>)FarmBlock.MOISTURE);
        if (isNearWater(xd, fk) || xd.isRainingAt(fk.above())) {
            if (integer6 < 7) {
                xd.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Integer>setValue((Property<Comparable>)FarmBlock.MOISTURE, 7), 2);
            }
        }
        else if (integer6 > 0) {
            xd.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Integer>setValue((Property<Comparable>)FarmBlock.MOISTURE, integer6 - 1), 2);
        }
        else if (!isUnderCrops(xd, fk)) {
            turnToDirt(byj, xd, fk);
        }
    }
    
    @Override
    public void fallOn(final Level bjw, final BlockPos fk, final Entity akq, final float float4) {
        if (!bjw.isClientSide && bjw.random.nextFloat() < float4 - 0.5f && akq instanceof LivingEntity && (akq instanceof Player || bjw.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && akq.getBbWidth() * akq.getBbWidth() * akq.getBbHeight() > 0.512f) {
            turnToDirt(bjw.getBlockState(fk), bjw, fk);
        }
        super.fallOn(bjw, fk, akq, float4);
    }
    
    public static void turnToDirt(final BlockState byj, final Level bjw, final BlockPos fk) {
        bjw.setBlockAndUpdate(fk, Block.pushEntitiesUp(byj, Blocks.DIRT.defaultBlockState(), bjw, fk));
    }
    
    private static boolean isUnderCrops(final BlockGetter bjg, final BlockPos fk) {
        final Block bph3 = bjg.getBlockState(fk.above()).getBlock();
        return bph3 instanceof CropBlock || bph3 instanceof StemBlock || bph3 instanceof AttachedStemBlock;
    }
    
    private static boolean isNearWater(final LevelReader bjz, final BlockPos fk) {
        for (final BlockPos fk2 : BlockPos.betweenClosed(fk.offset(-4, 0, -4), fk.offset(4, 1, 4))) {
            if (bjz.getFluidState(fk2).is(FluidTags.WATER)) {
                return true;
            }
        }
        return false;
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(FarmBlock.MOISTURE);
    }
    
    @Override
    public boolean isPathfindable(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final PathComputationType cqr) {
        return false;
    }
    
    @Override
    public boolean isViewBlocking(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return true;
    }
    
    static {
        MOISTURE = BlockStateProperties.MOISTURE;
        SHAPE = Block.box(0.0, 0.0, 0.0, 16.0, 15.0, 16.0);
    }
}
