package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
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.LevelReader;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.entity.player.Player;
import java.util.Random;
import net.minecraft.world.level.Level;
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.BlockBehaviour;
import net.minecraft.world.phys.shapes.Shapes;
import java.util.stream.IntStream;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.StairsShape;
import net.minecraft.world.level.block.state.properties.Half;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;

public class StairBlock extends Block implements SimpleWaterloggedBlock {
    public static final DirectionProperty FACING;
    public static final EnumProperty<Half> HALF;
    public static final EnumProperty<StairsShape> SHAPE;
    public static final BooleanProperty WATERLOGGED;
    protected static final VoxelShape TOP_AABB;
    protected static final VoxelShape BOTTOM_AABB;
    protected static final VoxelShape OCTET_NNN;
    protected static final VoxelShape OCTET_NNP;
    protected static final VoxelShape OCTET_NPN;
    protected static final VoxelShape OCTET_NPP;
    protected static final VoxelShape OCTET_PNN;
    protected static final VoxelShape OCTET_PNP;
    protected static final VoxelShape OCTET_PPN;
    protected static final VoxelShape OCTET_PPP;
    protected static final VoxelShape[] TOP_SHAPES;
    protected static final VoxelShape[] BOTTOM_SHAPES;
    private static final int[] SHAPE_BY_STATE;
    private final Block base;
    private final BlockState baseState;
    
    private static VoxelShape[] makeShapes(final VoxelShape dfg1, final VoxelShape dfg2, final VoxelShape dfg3, final VoxelShape dfg4, final VoxelShape dfg5) {
        return IntStream.range(0, 16).mapToObj(integer -> makeStairShape(integer, dfg1, dfg2, dfg3, dfg4, dfg5)).<VoxelShape>toArray(VoxelShape[]::new);
    }
    
    private static VoxelShape makeStairShape(final int integer, final VoxelShape dfg2, final VoxelShape dfg3, final VoxelShape dfg4, final VoxelShape dfg5, final VoxelShape dfg6) {
        VoxelShape dfg7 = dfg2;
        if ((integer & 0x1) != 0x0) {
            dfg7 = Shapes.or(dfg7, dfg3);
        }
        if ((integer & 0x2) != 0x0) {
            dfg7 = Shapes.or(dfg7, dfg4);
        }
        if ((integer & 0x4) != 0x0) {
            dfg7 = Shapes.or(dfg7, dfg5);
        }
        if ((integer & 0x8) != 0x0) {
            dfg7 = Shapes.or(dfg7, dfg6);
        }
        return dfg7;
    }
    
    protected StairBlock(final BlockState cfj, final Properties c) {
        super(c);
        this.registerDefaultState((((((StateHolder<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)StairBlock.FACING, Direction.NORTH)).setValue(StairBlock.HALF, Half.BOTTOM)).setValue(StairBlock.SHAPE, StairsShape.STRAIGHT)).<Comparable, Boolean>setValue((Property<Comparable>)StairBlock.WATERLOGGED, false));
        this.base = cfj.getBlock();
        this.baseState = cfj;
    }
    
    @Override
    public boolean useShapeForLightOcclusion(final BlockState cfj) {
        return true;
    }
    
    @Override
    public VoxelShape getShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return ((cfj.<Half>getValue(StairBlock.HALF) == Half.TOP) ? StairBlock.TOP_SHAPES : StairBlock.BOTTOM_SHAPES)[StairBlock.SHAPE_BY_STATE[this.getShapeIndex(cfj)]];
    }
    
    private int getShapeIndex(final BlockState cfj) {
        return cfj.<StairsShape>getValue(StairBlock.SHAPE).ordinal() * 4 + cfj.<Direction>getValue((Property<Direction>)StairBlock.FACING).get2DDataValue();
    }
    
    @Override
    public void animateTick(final BlockState cfj, final Level bqb, final BlockPos fu, final Random random) {
        this.base.animateTick(cfj, bqb, fu, random);
    }
    
    @Override
    public void attack(final BlockState cfj, final Level bqb, final BlockPos fu, final Player bec) {
        this.baseState.attack(bqb, fu, bec);
    }
    
    @Override
    public void destroy(final LevelAccessor bqc, final BlockPos fu, final BlockState cfj) {
        this.base.destroy(bqc, fu, cfj);
    }
    
    @Override
    public float getExplosionResistance() {
        return this.base.getExplosionResistance();
    }
    
    @Override
    public void onPlace(final BlockState cfj1, final Level bqb, final BlockPos fu, final BlockState cfj4, final boolean boolean5) {
        if (cfj1.is(cfj1.getBlock())) {
            return;
        }
        this.baseState.neighborChanged(bqb, fu, Blocks.AIR, fu, false);
        this.base.onPlace(this.baseState, bqb, fu, cfj4, false);
    }
    
    @Override
    public void onRemove(final BlockState cfj1, final Level bqb, final BlockPos fu, final BlockState cfj4, final boolean boolean5) {
        if (cfj1.is(cfj4.getBlock())) {
            return;
        }
        this.baseState.onRemove(bqb, fu, cfj4, boolean5);
    }
    
    @Override
    public void stepOn(final Level bqb, final BlockPos fu, final Entity aom) {
        this.base.stepOn(bqb, fu, aom);
    }
    
    @Override
    public boolean isRandomlyTicking(final BlockState cfj) {
        return this.base.isRandomlyTicking(cfj);
    }
    
    @Override
    public void randomTick(final BlockState cfj, final ServerLevel zd, final BlockPos fu, final Random random) {
        this.base.randomTick(cfj, zd, fu, random);
    }
    
    @Override
    public void tick(final BlockState cfj, final ServerLevel zd, final BlockPos fu, final Random random) {
        this.base.tick(cfj, zd, fu, random);
    }
    
    @Override
    public InteractionResult use(final BlockState cfj, final Level bqb, final BlockPos fu, final Player bec, final InteractionHand anf, final BlockHitResult deh) {
        return this.baseState.use(bqb, bec, anf, deh);
    }
    
    @Override
    public void wasExploded(final Level bqb, final BlockPos fu, final Explosion bpt) {
        this.base.wasExploded(bqb, fu, bpt);
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bin) {
        final Direction fz3 = bin.getClickedFace();
        final BlockPos fu4 = bin.getClickedPos();
        final FluidState cxa5 = bin.getLevel().getFluidState(fu4);
        final BlockState cfj6 = ((((StateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)StairBlock.FACING, bin.getHorizontalDirection())).setValue(StairBlock.HALF, (fz3 == Direction.DOWN || (fz3 != Direction.UP && bin.getClickLocation().y - fu4.getY() > 0.5)) ? Half.TOP : Half.BOTTOM)).<Comparable, Boolean>setValue((Property<Comparable>)StairBlock.WATERLOGGED, cxa5.getType() == Fluids.WATER);
        return ((StateHolder<O, BlockState>)cfj6).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, getStairsShape(cfj6, bin.getLevel(), fu4));
    }
    
    @Override
    public BlockState updateShape(final BlockState cfj1, final Direction fz, final BlockState cfj3, final LevelAccessor bqc, final BlockPos fu5, final BlockPos fu6) {
        if (cfj1.<Boolean>getValue((Property<Boolean>)StairBlock.WATERLOGGED)) {
            bqc.getLiquidTicks().scheduleTick(fu5, Fluids.WATER, Fluids.WATER.getTickDelay(bqc));
        }
        if (fz.getAxis().isHorizontal()) {
            return ((StateHolder<O, BlockState>)cfj1).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, getStairsShape(cfj1, bqc, fu5));
        }
        return super.updateShape(cfj1, fz, cfj3, bqc, fu5, fu6);
    }
    
    private static StairsShape getStairsShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu) {
        final Direction fz4 = cfj.<Direction>getValue((Property<Direction>)StairBlock.FACING);
        final BlockState cfj2 = bpg.getBlockState(fu.relative(fz4));
        if (isStairs(cfj2) && cfj.<Half>getValue(StairBlock.HALF) == cfj2.<Half>getValue(StairBlock.HALF)) {
            final Direction fz5 = cfj2.<Direction>getValue((Property<Direction>)StairBlock.FACING);
            if (fz5.getAxis() != cfj.<Direction>getValue((Property<Direction>)StairBlock.FACING).getAxis() && canTakeShape(cfj, bpg, fu, fz5.getOpposite())) {
                if (fz5 == fz4.getCounterClockWise()) {
                    return StairsShape.OUTER_LEFT;
                }
                return StairsShape.OUTER_RIGHT;
            }
        }
        final BlockState cfj3 = bpg.getBlockState(fu.relative(fz4.getOpposite()));
        if (isStairs(cfj3) && cfj.<Half>getValue(StairBlock.HALF) == cfj3.<Half>getValue(StairBlock.HALF)) {
            final Direction fz6 = cfj3.<Direction>getValue((Property<Direction>)StairBlock.FACING);
            if (fz6.getAxis() != cfj.<Direction>getValue((Property<Direction>)StairBlock.FACING).getAxis() && canTakeShape(cfj, bpg, fu, fz6)) {
                if (fz6 == fz4.getCounterClockWise()) {
                    return StairsShape.INNER_LEFT;
                }
                return StairsShape.INNER_RIGHT;
            }
        }
        return StairsShape.STRAIGHT;
    }
    
    private static boolean canTakeShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final Direction fz) {
        final BlockState cfj2 = bpg.getBlockState(fu.relative(fz));
        return !isStairs(cfj2) || cfj2.<Comparable>getValue((Property<Comparable>)StairBlock.FACING) != cfj.<Comparable>getValue((Property<Comparable>)StairBlock.FACING) || cfj2.<Half>getValue(StairBlock.HALF) != cfj.<Half>getValue(StairBlock.HALF);
    }
    
    public static boolean isStairs(final BlockState cfj) {
        return cfj.getBlock() instanceof StairBlock;
    }
    
    @Override
    public BlockState rotate(final BlockState cfj, final Rotation cap) {
        return ((StateHolder<O, BlockState>)cfj).<Comparable, Direction>setValue((Property<Comparable>)StairBlock.FACING, cap.rotate(cfj.<Direction>getValue((Property<Direction>)StairBlock.FACING)));
    }
    
    @Override
    public BlockState mirror(final BlockState cfj, final Mirror bzj) {
        final Direction fz4 = cfj.<Direction>getValue((Property<Direction>)StairBlock.FACING);
        final StairsShape cgp5 = cfj.<StairsShape>getValue(StairBlock.SHAPE);
        Label_0335: {
            switch (bzj) {
                case LEFT_RIGHT: {
                    if (fz4.getAxis() != Direction.Axis.Z) {
                        break;
                    }
                    switch (cgp5) {
                        case INNER_LEFT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_RIGHT);
                        }
                        case INNER_RIGHT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_LEFT);
                        }
                        case OUTER_LEFT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT);
                        }
                        case OUTER_RIGHT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT);
                        }
                        default: {
                            return cfj.rotate(Rotation.CLOCKWISE_180);
                        }
                    }
                    break;
                }
                case FRONT_BACK: {
                    if (fz4.getAxis() != Direction.Axis.X) {
                        break;
                    }
                    switch (cgp5) {
                        case INNER_LEFT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_LEFT);
                        }
                        case INNER_RIGHT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_RIGHT);
                        }
                        case OUTER_LEFT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT);
                        }
                        case OUTER_RIGHT: {
                            return ((StateHolder<O, BlockState>)cfj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT);
                        }
                        case STRAIGHT: {
                            return cfj.rotate(Rotation.CLOCKWISE_180);
                        }
                        default: {
                            break Label_0335;
                        }
                    }
                    break;
                }
            }
        }
        return super.mirror(cfj, bzj);
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(StairBlock.FACING, StairBlock.HALF, StairBlock.SHAPE, StairBlock.WATERLOGGED);
    }
    
    @Override
    public FluidState getFluidState(final BlockState cfj) {
        if (cfj.<Boolean>getValue((Property<Boolean>)StairBlock.WATERLOGGED)) {
            return Fluids.WATER.getSource(false);
        }
        return super.getFluidState(cfj);
    }
    
    @Override
    public boolean isPathfindable(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final PathComputationType czg) {
        return false;
    }
    
    static {
        FACING = HorizontalDirectionalBlock.FACING;
        HALF = BlockStateProperties.HALF;
        SHAPE = BlockStateProperties.STAIRS_SHAPE;
        WATERLOGGED = BlockStateProperties.WATERLOGGED;
        TOP_AABB = SlabBlock.TOP_AABB;
        BOTTOM_AABB = SlabBlock.BOTTOM_AABB;
        OCTET_NNN = Block.box(0.0, 0.0, 0.0, 8.0, 8.0, 8.0);
        OCTET_NNP = Block.box(0.0, 0.0, 8.0, 8.0, 8.0, 16.0);
        OCTET_NPN = Block.box(0.0, 8.0, 0.0, 8.0, 16.0, 8.0);
        OCTET_NPP = Block.box(0.0, 8.0, 8.0, 8.0, 16.0, 16.0);
        OCTET_PNN = Block.box(8.0, 0.0, 0.0, 16.0, 8.0, 8.0);
        OCTET_PNP = Block.box(8.0, 0.0, 8.0, 16.0, 8.0, 16.0);
        OCTET_PPN = Block.box(8.0, 8.0, 0.0, 16.0, 16.0, 8.0);
        OCTET_PPP = Block.box(8.0, 8.0, 8.0, 16.0, 16.0, 16.0);
        TOP_SHAPES = makeShapes(StairBlock.TOP_AABB, StairBlock.OCTET_NNN, StairBlock.OCTET_PNN, StairBlock.OCTET_NNP, StairBlock.OCTET_PNP);
        BOTTOM_SHAPES = makeShapes(StairBlock.BOTTOM_AABB, StairBlock.OCTET_NPN, StairBlock.OCTET_PPN, StairBlock.OCTET_NPP, StairBlock.OCTET_PPP);
        SHAPE_BY_STATE = new int[] { 12, 5, 3, 10, 14, 13, 7, 11, 13, 7, 11, 14, 8, 4, 1, 2, 4, 1, 2, 8 };
    }
}
