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 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.LevelReader;
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.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 cwf1, final VoxelShape cwf2, final VoxelShape cwf3, final VoxelShape cwf4, final VoxelShape cwf5) {
        return IntStream.range(0, 16).mapToObj(integer -> makeStairShape(integer, cwf1, cwf2, cwf3, cwf4, cwf5)).<VoxelShape>toArray(VoxelShape[]::new);
    }
    
    private static VoxelShape makeStairShape(final int integer, final VoxelShape cwf2, final VoxelShape cwf3, final VoxelShape cwf4, final VoxelShape cwf5, final VoxelShape cwf6) {
        VoxelShape cwf7 = cwf2;
        if ((integer & 0x1) != 0x0) {
            cwf7 = Shapes.or(cwf7, cwf3);
        }
        if ((integer & 0x2) != 0x0) {
            cwf7 = Shapes.or(cwf7, cwf4);
        }
        if ((integer & 0x4) != 0x0) {
            cwf7 = Shapes.or(cwf7, cwf5);
        }
        if ((integer & 0x8) != 0x0) {
            cwf7 = Shapes.or(cwf7, cwf6);
        }
        return cwf7;
    }
    
    protected StairBlock(final BlockState byj, final Properties c) {
        super(c);
        this.registerDefaultState((((((AbstractStateHolder<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 = byj.getBlock();
        this.baseState = byj;
    }
    
    @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 ((byj.<Half>getValue(StairBlock.HALF) == Half.TOP) ? StairBlock.TOP_SHAPES : StairBlock.BOTTOM_SHAPES)[StairBlock.SHAPE_BY_STATE[this.getShapeIndex(byj)]];
    }
    
    private int getShapeIndex(final BlockState byj) {
        return byj.<StairsShape>getValue(StairBlock.SHAPE).ordinal() * 4 + byj.<Direction>getValue((Property<Direction>)StairBlock.FACING).get2DDataValue();
    }
    
    @Override
    public void animateTick(final BlockState byj, final Level bjw, final BlockPos fk, final Random random) {
        this.base.animateTick(byj, bjw, fk, random);
    }
    
    @Override
    public void attack(final BlockState byj, final Level bjw, final BlockPos fk, final Player ayj) {
        this.baseState.attack(bjw, fk, ayj);
    }
    
    @Override
    public void destroy(final LevelAccessor bjx, final BlockPos fk, final BlockState byj) {
        this.base.destroy(bjx, fk, byj);
    }
    
    @Override
    public float getExplosionResistance() {
        return this.base.getExplosionResistance();
    }
    
    @Override
    public int getTickDelay(final LevelReader bjz) {
        return this.base.getTickDelay(bjz);
    }
    
    @Override
    public void onPlace(final BlockState byj1, final Level bjw, final BlockPos fk, final BlockState byj4, final boolean boolean5) {
        if (byj1.getBlock() == byj1.getBlock()) {
            return;
        }
        this.baseState.neighborChanged(bjw, fk, Blocks.AIR, fk, false);
        this.base.onPlace(this.baseState, bjw, fk, byj4, false);
    }
    
    @Override
    public void onRemove(final BlockState byj1, final Level bjw, final BlockPos fk, final BlockState byj4, final boolean boolean5) {
        if (byj1.getBlock() == byj4.getBlock()) {
            return;
        }
        this.baseState.onRemove(bjw, fk, byj4, boolean5);
    }
    
    @Override
    public void stepOn(final Level bjw, final BlockPos fk, final Entity akq) {
        this.base.stepOn(bjw, fk, akq);
    }
    
    @Override
    public void tick(final BlockState byj, final ServerLevel xd, final BlockPos fk, final Random random) {
        this.base.tick(byj, xd, fk, random);
    }
    
    @Override
    public InteractionResult use(final BlockState byj, final Level bjw, final BlockPos fk, final Player ayj, final InteractionHand ajk, final BlockHitResult cvg) {
        return this.baseState.use(bjw, ayj, ajk, cvg);
    }
    
    @Override
    public void wasExploded(final Level bjw, final BlockPos fk, final Explosion bjp) {
        this.base.wasExploded(bjw, fk, bjp);
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bcq) {
        final Direction fp3 = bcq.getClickedFace();
        final BlockPos fk4 = bcq.getClickedPos();
        final FluidState coj5 = bcq.getLevel().getFluidState(fk4);
        final BlockState byj6 = ((((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)StairBlock.FACING, bcq.getHorizontalDirection())).setValue(StairBlock.HALF, (fp3 == Direction.DOWN || (fp3 != Direction.UP && bcq.getClickLocation().y - fk4.getY() > 0.5)) ? Half.TOP : Half.BOTTOM)).<Comparable, Boolean>setValue((Property<Comparable>)StairBlock.WATERLOGGED, coj5.getType() == Fluids.WATER);
        return ((AbstractStateHolder<O, BlockState>)byj6).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, getStairsShape(byj6, bcq.getLevel(), fk4));
    }
    
    @Override
    public BlockState updateShape(final BlockState byj1, final Direction fp, final BlockState byj3, final LevelAccessor bjx, final BlockPos fk5, final BlockPos fk6) {
        if (byj1.<Boolean>getValue((Property<Boolean>)StairBlock.WATERLOGGED)) {
            bjx.getLiquidTicks().scheduleTick(fk5, Fluids.WATER, Fluids.WATER.getTickDelay(bjx));
        }
        if (fp.getAxis().isHorizontal()) {
            return ((AbstractStateHolder<O, BlockState>)byj1).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, getStairsShape(byj1, bjx, fk5));
        }
        return super.updateShape(byj1, fp, byj3, bjx, fk5, fk6);
    }
    
    private static StairsShape getStairsShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        final Direction fp4 = byj.<Direction>getValue((Property<Direction>)StairBlock.FACING);
        final BlockState byj2 = bjg.getBlockState(fk.relative(fp4));
        if (isStairs(byj2) && byj.<Half>getValue(StairBlock.HALF) == byj2.<Half>getValue(StairBlock.HALF)) {
            final Direction fp5 = byj2.<Direction>getValue((Property<Direction>)StairBlock.FACING);
            if (fp5.getAxis() != byj.<Direction>getValue((Property<Direction>)StairBlock.FACING).getAxis() && canTakeShape(byj, bjg, fk, fp5.getOpposite())) {
                if (fp5 == fp4.getCounterClockWise()) {
                    return StairsShape.OUTER_LEFT;
                }
                return StairsShape.OUTER_RIGHT;
            }
        }
        final BlockState byj3 = bjg.getBlockState(fk.relative(fp4.getOpposite()));
        if (isStairs(byj3) && byj.<Half>getValue(StairBlock.HALF) == byj3.<Half>getValue(StairBlock.HALF)) {
            final Direction fp6 = byj3.<Direction>getValue((Property<Direction>)StairBlock.FACING);
            if (fp6.getAxis() != byj.<Direction>getValue((Property<Direction>)StairBlock.FACING).getAxis() && canTakeShape(byj, bjg, fk, fp6)) {
                if (fp6 == fp4.getCounterClockWise()) {
                    return StairsShape.INNER_LEFT;
                }
                return StairsShape.INNER_RIGHT;
            }
        }
        return StairsShape.STRAIGHT;
    }
    
    private static boolean canTakeShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final Direction fp) {
        final BlockState byj2 = bjg.getBlockState(fk.relative(fp));
        return !isStairs(byj2) || byj2.<Comparable>getValue((Property<Comparable>)StairBlock.FACING) != byj.<Comparable>getValue((Property<Comparable>)StairBlock.FACING) || byj2.<Half>getValue(StairBlock.HALF) != byj.<Half>getValue(StairBlock.HALF);
    }
    
    public static boolean isStairs(final BlockState byj) {
        return byj.getBlock() instanceof StairBlock;
    }
    
    @Override
    public BlockState rotate(final BlockState byj, final Rotation btu) {
        return ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Direction>setValue((Property<Comparable>)StairBlock.FACING, btu.rotate(byj.<Direction>getValue((Property<Direction>)StairBlock.FACING)));
    }
    
    @Override
    public BlockState mirror(final BlockState byj, final Mirror bsu) {
        final Direction fp4 = byj.<Direction>getValue((Property<Direction>)StairBlock.FACING);
        final StairsShape bzq5 = byj.<StairsShape>getValue(StairBlock.SHAPE);
        Label_0335: {
            switch (bsu) {
                case LEFT_RIGHT: {
                    if (fp4.getAxis() != Direction.Axis.Z) {
                        break;
                    }
                    switch (bzq5) {
                        case INNER_LEFT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_RIGHT);
                        }
                        case INNER_RIGHT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_LEFT);
                        }
                        case OUTER_LEFT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT);
                        }
                        case OUTER_RIGHT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT);
                        }
                        default: {
                            return byj.rotate(Rotation.CLOCKWISE_180);
                        }
                    }
                    break;
                }
                case FRONT_BACK: {
                    if (fp4.getAxis() != Direction.Axis.X) {
                        break;
                    }
                    switch (bzq5) {
                        case INNER_LEFT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_LEFT);
                        }
                        case INNER_RIGHT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.INNER_RIGHT);
                        }
                        case OUTER_LEFT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_RIGHT);
                        }
                        case OUTER_RIGHT: {
                            return ((AbstractStateHolder<O, BlockState>)byj.rotate(Rotation.CLOCKWISE_180)).<StairsShape, StairsShape>setValue(StairBlock.SHAPE, StairsShape.OUTER_LEFT);
                        }
                        case STRAIGHT: {
                            return byj.rotate(Rotation.CLOCKWISE_180);
                        }
                        default: {
                            break Label_0335;
                        }
                    }
                    break;
                }
            }
        }
        return super.mirror(byj, bsu);
    }
    
    @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 byj) {
        if (byj.<Boolean>getValue((Property<Boolean>)StairBlock.WATERLOGGED)) {
            return Fluids.WATER.getSource(false);
        }
        return super.getFluidState(byj);
    }
    
    @Override
    public boolean isPathfindable(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final PathComputationType cqr) {
        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 };
    }
}
