package net.minecraft.world.level.block.piston;

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 net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import java.util.Iterator;
import java.util.List;
import net.minecraft.world.level.LevelAccessor;
import java.util.Map;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.level.block.state.properties.PistonType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.DirectionalBlock;

public class PistonBaseBlock extends DirectionalBlock {
    public static final BooleanProperty EXTENDED;
    protected static final VoxelShape EAST_AABB;
    protected static final VoxelShape WEST_AABB;
    protected static final VoxelShape SOUTH_AABB;
    protected static final VoxelShape NORTH_AABB;
    protected static final VoxelShape UP_AABB;
    protected static final VoxelShape DOWN_AABB;
    private final boolean isSticky;
    
    public PistonBaseBlock(final boolean boolean1, final Properties c) {
        super(c);
        this.registerDefaultState((((AbstractStateHolder<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)PistonBaseBlock.FACING, Direction.NORTH)).<Comparable, Boolean>setValue((Property<Comparable>)PistonBaseBlock.EXTENDED, false));
        this.isSticky = boolean1;
    }
    
    @Override
    public boolean isSuffocating(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return !byj.<Boolean>getValue((Property<Boolean>)PistonBaseBlock.EXTENDED);
    }
    
    @Override
    public VoxelShape getShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        if (!byj.<Boolean>getValue((Property<Boolean>)PistonBaseBlock.EXTENDED)) {
            return Shapes.block();
        }
        switch (byj.<Direction>getValue((Property<Direction>)PistonBaseBlock.FACING)) {
            case DOWN: {
                return PistonBaseBlock.DOWN_AABB;
            }
            default: {
                return PistonBaseBlock.UP_AABB;
            }
            case NORTH: {
                return PistonBaseBlock.NORTH_AABB;
            }
            case SOUTH: {
                return PistonBaseBlock.SOUTH_AABB;
            }
            case WEST: {
                return PistonBaseBlock.WEST_AABB;
            }
            case EAST: {
                return PistonBaseBlock.EAST_AABB;
            }
        }
    }
    
    @Override
    public boolean isRedstoneConductor(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        return false;
    }
    
    @Override
    public void setPlacedBy(final Level bjw, final BlockPos fk, final BlockState byj, final LivingEntity akz, final ItemStack ben) {
        if (!bjw.isClientSide) {
            this.checkIfExtend(bjw, fk, byj);
        }
    }
    
    @Override
    public void neighborChanged(final BlockState byj, final Level bjw, final BlockPos fk3, final Block bph, final BlockPos fk5, final boolean boolean6) {
        if (!bjw.isClientSide) {
            this.checkIfExtend(bjw, fk3, byj);
        }
    }
    
    @Override
    public void onPlace(final BlockState byj1, final Level bjw, final BlockPos fk, final BlockState byj4, final boolean boolean5) {
        if (byj4.getBlock() == byj1.getBlock()) {
            return;
        }
        if (!bjw.isClientSide && bjw.getBlockEntity(fk) == null) {
            this.checkIfExtend(bjw, fk, byj1);
        }
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bcq) {
        return (((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)PistonBaseBlock.FACING, bcq.getNearestLookingDirection().getOpposite())).<Comparable, Boolean>setValue((Property<Comparable>)PistonBaseBlock.EXTENDED, false);
    }
    
    private void checkIfExtend(final Level bjw, final BlockPos fk, final BlockState byj) {
        final Direction fp5 = byj.<Direction>getValue((Property<Direction>)PistonBaseBlock.FACING);
        final boolean boolean6 = this.getNeighborSignal(bjw, fk, fp5);
        if (boolean6 && !byj.<Boolean>getValue((Property<Boolean>)PistonBaseBlock.EXTENDED)) {
            if (new PistonStructureResolver(bjw, fk, fp5, true).resolve()) {
                bjw.blockEvent(fk, this, 0, fp5.get3DDataValue());
            }
        }
        else if (!boolean6 && byj.<Boolean>getValue((Property<Boolean>)PistonBaseBlock.EXTENDED)) {
            final BlockPos fk2 = fk.relative(fp5, 2);
            final BlockState byj2 = bjw.getBlockState(fk2);
            int integer9 = 1;
            if (byj2.getBlock() == Blocks.MOVING_PISTON && byj2.<Comparable>getValue((Property<Comparable>)PistonBaseBlock.FACING) == fp5) {
                final BlockEntity bwl10 = bjw.getBlockEntity(fk2);
                if (bwl10 instanceof PistonMovingBlockEntity) {
                    final PistonMovingBlockEntity byf11 = (PistonMovingBlockEntity)bwl10;
                    if (byf11.isExtending() && (byf11.getProgress(0.0f) < 0.5f || bjw.getGameTime() == byf11.getLastTicked() || ((ServerLevel)bjw).isHandlingTick())) {
                        integer9 = 2;
                    }
                }
            }
            bjw.blockEvent(fk, this, integer9, fp5.get3DDataValue());
        }
    }
    
    private boolean getNeighborSignal(final Level bjw, final BlockPos fk, final Direction fp) {
        for (final Direction fp2 : Direction.values()) {
            if (fp2 != fp && bjw.hasSignal(fk.relative(fp2), fp2)) {
                return true;
            }
        }
        if (bjw.hasSignal(fk, Direction.DOWN)) {
            return true;
        }
        final BlockPos fk2 = fk.above();
        for (final Direction fp3 : Direction.values()) {
            if (fp3 != Direction.DOWN && bjw.hasSignal(fk2.relative(fp3), fp3)) {
                return true;
            }
        }
        return false;
    }
    
    @Override
    public boolean triggerEvent(final BlockState byj, final Level bjw, final BlockPos fk, final int integer4, final int integer5) {
        final Direction fp7 = byj.<Direction>getValue((Property<Direction>)PistonBaseBlock.FACING);
        if (!bjw.isClientSide) {
            final boolean boolean8 = this.getNeighborSignal(bjw, fk, fp7);
            if (boolean8 && (integer4 == 1 || integer4 == 2)) {
                bjw.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Boolean>setValue((Property<Comparable>)PistonBaseBlock.EXTENDED, true), 2);
                return false;
            }
            if (!boolean8 && integer4 == 0) {
                return false;
            }
        }
        if (integer4 == 0) {
            if (!this.moveBlocks(bjw, fk, fp7, true)) {
                return false;
            }
            bjw.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Boolean>setValue((Property<Comparable>)PistonBaseBlock.EXTENDED, true), 67);
            bjw.playSound(null, fk, SoundEvents.PISTON_EXTEND, SoundSource.BLOCKS, 0.5f, bjw.random.nextFloat() * 0.25f + 0.6f);
        }
        else if (integer4 == 1 || integer4 == 2) {
            final BlockEntity bwl8 = bjw.getBlockEntity(fk.relative(fp7));
            if (bwl8 instanceof PistonMovingBlockEntity) {
                ((PistonMovingBlockEntity)bwl8).finalTick();
            }
            bjw.setBlock(fk, (((AbstractStateHolder<O, BlockState>)Blocks.MOVING_PISTON.defaultBlockState()).setValue((Property<Comparable>)MovingPistonBlock.FACING, fp7)).<PistonType, PistonType>setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT), 3);
            bjw.setBlockEntity(fk, MovingPistonBlock.newMovingBlockEntity(((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)PistonBaseBlock.FACING, Direction.from3DDataValue(integer5 & 0x7)), fp7, false, true));
            if (this.isSticky) {
                final BlockPos fk2 = fk.offset(fp7.getStepX() * 2, fp7.getStepY() * 2, fp7.getStepZ() * 2);
                final BlockState byj2 = bjw.getBlockState(fk2);
                final Block bph11 = byj2.getBlock();
                boolean boolean9 = false;
                if (bph11 == Blocks.MOVING_PISTON) {
                    final BlockEntity bwl9 = bjw.getBlockEntity(fk2);
                    if (bwl9 instanceof PistonMovingBlockEntity) {
                        final PistonMovingBlockEntity byf14 = (PistonMovingBlockEntity)bwl9;
                        if (byf14.getDirection() == fp7 && byf14.isExtending()) {
                            byf14.finalTick();
                            boolean9 = true;
                        }
                    }
                }
                if (!boolean9) {
                    if (integer4 == 1 && !byj2.isAir() && isPushable(byj2, bjw, fk2, fp7.getOpposite(), false, fp7) && (byj2.getPistonPushReaction() == PushReaction.NORMAL || bph11 == Blocks.PISTON || bph11 == Blocks.STICKY_PISTON)) {
                        this.moveBlocks(bjw, fk, fp7, false);
                    }
                    else {
                        bjw.removeBlock(fk.relative(fp7), false);
                    }
                }
            }
            else {
                bjw.removeBlock(fk.relative(fp7), false);
            }
            bjw.playSound(null, fk, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5f, bjw.random.nextFloat() * 0.15f + 0.6f);
        }
        return true;
    }
    
    public static boolean isPushable(final BlockState byj, final Level bjw, final BlockPos fk, final Direction fp4, final boolean boolean5, final Direction fp6) {
        final Block bph7 = byj.getBlock();
        if (bph7 == Blocks.OBSIDIAN) {
            return false;
        }
        if (!bjw.getWorldBorder().isWithinBounds(fk)) {
            return false;
        }
        if (fk.getY() < 0 || (fp4 == Direction.DOWN && fk.getY() == 0)) {
            return false;
        }
        if (fk.getY() > bjw.getMaxBuildHeight() - 1 || (fp4 == Direction.UP && fk.getY() == bjw.getMaxBuildHeight() - 1)) {
            return false;
        }
        if (bph7 == Blocks.PISTON || bph7 == Blocks.STICKY_PISTON) {
            if (byj.<Boolean>getValue((Property<Boolean>)PistonBaseBlock.EXTENDED)) {
                return false;
            }
        }
        else {
            if (byj.getDestroySpeed(bjw, fk) == -1.0f) {
                return false;
            }
            switch (byj.getPistonPushReaction()) {
                case BLOCK: {
                    return false;
                }
                case DESTROY: {
                    return boolean5;
                }
                case PUSH_ONLY: {
                    return fp4 == fp6;
                }
            }
        }
        return !bph7.isEntityBlock();
    }
    
    private boolean moveBlocks(final Level bjw, final BlockPos fk, final Direction fp, final boolean boolean4) {
        final BlockPos fk2 = fk.relative(fp);
        if (!boolean4 && bjw.getBlockState(fk2).getBlock() == Blocks.PISTON_HEAD) {
            bjw.setBlock(fk2, Blocks.AIR.defaultBlockState(), 20);
        }
        final PistonStructureResolver byg7 = new PistonStructureResolver(bjw, fk, fp, boolean4);
        if (!byg7.resolve()) {
            return false;
        }
        final Map<BlockPos, BlockState> map8 = Maps.newHashMap();
        final List<BlockPos> list9 = byg7.getToPush();
        final List<BlockState> list10 = Lists.newArrayList();
        for (int integer11 = 0; integer11 < list9.size(); ++integer11) {
            final BlockPos fk3 = list9.get(integer11);
            final BlockState byj13 = bjw.getBlockState(fk3);
            list10.add(byj13);
            map8.put(fk3, byj13);
        }
        final List<BlockPos> list11 = byg7.getToDestroy();
        int integer12 = list9.size() + list11.size();
        final BlockState[] arr13 = new BlockState[integer12];
        final Direction fp2 = boolean4 ? fp : fp.getOpposite();
        for (int integer13 = list11.size() - 1; integer13 >= 0; --integer13) {
            final BlockPos fk4 = list11.get(integer13);
            final BlockState byj14 = bjw.getBlockState(fk4);
            final BlockEntity bwl18 = byj14.getBlock().isEntityBlock() ? bjw.getBlockEntity(fk4) : null;
            Block.dropResources(byj14, bjw, fk4, bwl18);
            bjw.setBlock(fk4, Blocks.AIR.defaultBlockState(), 18);
            arr13[--integer12] = byj14;
        }
        for (int integer13 = list9.size() - 1; integer13 >= 0; --integer13) {
            BlockPos fk4 = list9.get(integer13);
            final BlockState byj14 = bjw.getBlockState(fk4);
            fk4 = fk4.relative(fp2);
            map8.remove(fk4);
            bjw.setBlock(fk4, ((AbstractStateHolder<O, BlockState>)Blocks.MOVING_PISTON.defaultBlockState()).<Comparable, Direction>setValue((Property<Comparable>)PistonBaseBlock.FACING, fp), 68);
            bjw.setBlockEntity(fk4, MovingPistonBlock.newMovingBlockEntity(list10.get(integer13), fp, boolean4, false));
            arr13[--integer12] = byj14;
        }
        if (boolean4) {
            final PistonType bzl15 = this.isSticky ? PistonType.STICKY : PistonType.DEFAULT;
            final BlockState byj15 = (((AbstractStateHolder<O, BlockState>)Blocks.PISTON_HEAD.defaultBlockState()).setValue((Property<Comparable>)PistonHeadBlock.FACING, fp)).<PistonType, PistonType>setValue(PistonHeadBlock.TYPE, bzl15);
            final BlockState byj14 = (((AbstractStateHolder<O, BlockState>)Blocks.MOVING_PISTON.defaultBlockState()).setValue((Property<Comparable>)MovingPistonBlock.FACING, fp)).<PistonType, PistonType>setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT);
            map8.remove(fk2);
            bjw.setBlock(fk2, byj14, 68);
            bjw.setBlockEntity(fk2, MovingPistonBlock.newMovingBlockEntity(byj15, fp, true, true));
        }
        final BlockState byj16 = Blocks.AIR.defaultBlockState();
        for (final BlockPos fk5 : map8.keySet()) {
            bjw.setBlock(fk5, byj16, 82);
        }
        for (final Map.Entry<BlockPos, BlockState> entry17 : map8.entrySet()) {
            final BlockPos fk6 = entry17.getKey();
            final BlockState byj17 = entry17.getValue();
            byj17.updateIndirectNeighbourShapes(bjw, fk6, 2);
            byj16.updateNeighbourShapes(bjw, fk6, 2);
            byj16.updateIndirectNeighbourShapes(bjw, fk6, 2);
        }
        for (int integer14 = list11.size() - 1; integer14 >= 0; --integer14) {
            final BlockState byj14 = arr13[integer12++];
            final BlockPos fk6 = list11.get(integer14);
            byj14.updateIndirectNeighbourShapes(bjw, fk6, 2);
            bjw.updateNeighborsAt(fk6, byj14.getBlock());
        }
        for (int integer14 = list9.size() - 1; integer14 >= 0; --integer14) {
            bjw.updateNeighborsAt(list9.get(integer14), arr13[integer12++].getBlock());
        }
        if (boolean4) {
            bjw.updateNeighborsAt(fk2, Blocks.PISTON_HEAD);
        }
        return true;
    }
    
    @Override
    public BlockState rotate(final BlockState byj, final Rotation btu) {
        return ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Direction>setValue((Property<Comparable>)PistonBaseBlock.FACING, btu.rotate(byj.<Direction>getValue((Property<Direction>)PistonBaseBlock.FACING)));
    }
    
    @Override
    public BlockState mirror(final BlockState byj, final Mirror bsu) {
        return byj.rotate(bsu.getRotation(byj.<Direction>getValue((Property<Direction>)PistonBaseBlock.FACING)));
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(PistonBaseBlock.FACING, PistonBaseBlock.EXTENDED);
    }
    
    @Override
    public boolean useShapeForLightOcclusion(final BlockState byj) {
        return byj.<Boolean>getValue((Property<Boolean>)PistonBaseBlock.EXTENDED);
    }
    
    @Override
    public boolean isPathfindable(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final PathComputationType cqr) {
        return false;
    }
    
    static {
        EXTENDED = BlockStateProperties.EXTENDED;
        EAST_AABB = Block.box(0.0, 0.0, 0.0, 12.0, 16.0, 16.0);
        WEST_AABB = Block.box(4.0, 0.0, 0.0, 16.0, 16.0, 16.0);
        SOUTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 12.0);
        NORTH_AABB = Block.box(0.0, 0.0, 4.0, 16.0, 16.0, 16.0);
        UP_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 12.0, 16.0);
        DOWN_AABB = Block.box(0.0, 4.0, 0.0, 16.0, 16.0, 16.0);
    }
}
