package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.core.Direction;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.properties.RailShape;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.tags.Tag;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.shapes.VoxelShape;

public abstract class BaseRailBlock extends Block {
    protected static final VoxelShape FLAT_AABB;
    protected static final VoxelShape HALF_BLOCK_AABB;
    private final boolean isStraight;
    
    public static boolean isRail(final Level bqb, final BlockPos fu) {
        return isRail(bqb.getBlockState(fu));
    }
    
    public static boolean isRail(final BlockState cfj) {
        return cfj.is(BlockTags.RAILS) && cfj.getBlock() instanceof BaseRailBlock;
    }
    
    protected BaseRailBlock(final boolean boolean1, final Properties c) {
        super(c);
        this.isStraight = boolean1;
    }
    
    public boolean isStraight() {
        return this.isStraight;
    }
    
    @Override
    public VoxelShape getShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        final RailShape cgm6 = cfj.is(this) ? cfj.<RailShape>getValue(this.getShapeProperty()) : null;
        if (cgm6 != null && cgm6.isAscending()) {
            return BaseRailBlock.HALF_BLOCK_AABB;
        }
        return BaseRailBlock.FLAT_AABB;
    }
    
    @Override
    public boolean canSurvive(final BlockState cfj, final LevelReader bqd, final BlockPos fu) {
        return Block.canSupportRigidBlock(bqd, fu.below());
    }
    
    @Override
    public void onPlace(final BlockState cfj1, final Level bqb, final BlockPos fu, final BlockState cfj4, final boolean boolean5) {
        if (cfj4.is(cfj1.getBlock())) {
            return;
        }
        this.updateState(cfj1, bqb, fu, boolean5);
    }
    
    protected BlockState updateState(BlockState cfj, final Level bqb, final BlockPos fu, final boolean boolean4) {
        cfj = this.updateDir(bqb, fu, cfj, true);
        if (this.isStraight) {
            cfj.neighborChanged(bqb, fu, this, fu, boolean4);
        }
        return cfj;
    }
    
    @Override
    public void neighborChanged(final BlockState cfj, final Level bqb, final BlockPos fu3, final Block bvr, final BlockPos fu5, final boolean boolean6) {
        if (bqb.isClientSide) {
            return;
        }
        final RailShape cgm8 = cfj.<RailShape>getValue(this.getShapeProperty());
        if (shouldBeRemoved(fu3, bqb, cgm8) && !bqb.isEmptyBlock(fu3)) {
            if (!boolean6) {
                Block.dropResources(cfj, bqb, fu3);
            }
            bqb.removeBlock(fu3, boolean6);
        }
        else {
            this.updateState(cfj, bqb, fu3, bvr);
        }
    }
    
    private static boolean shouldBeRemoved(final BlockPos fu, final Level bqb, final RailShape cgm) {
        if (!Block.canSupportRigidBlock(bqb, fu.below())) {
            return true;
        }
        switch (cgm) {
            case ASCENDING_EAST: {
                return !Block.canSupportRigidBlock(bqb, fu.east());
            }
            case ASCENDING_WEST: {
                return !Block.canSupportRigidBlock(bqb, fu.west());
            }
            case ASCENDING_NORTH: {
                return !Block.canSupportRigidBlock(bqb, fu.north());
            }
            case ASCENDING_SOUTH: {
                return !Block.canSupportRigidBlock(bqb, fu.south());
            }
            default: {
                return false;
            }
        }
    }
    
    protected void updateState(final BlockState cfj, final Level bqb, final BlockPos fu, final Block bvr) {
    }
    
    protected BlockState updateDir(final Level bqb, final BlockPos fu, final BlockState cfj, final boolean boolean4) {
        if (bqb.isClientSide) {
            return cfj;
        }
        final RailShape cgm6 = cfj.<RailShape>getValue(this.getShapeProperty());
        return new RailState(bqb, fu, cfj).place(bqb.hasNeighborSignal(fu), boolean4, cgm6).getState();
    }
    
    @Override
    public PushReaction getPistonPushReaction(final BlockState cfj) {
        return PushReaction.NORMAL;
    }
    
    @Override
    public void onRemove(final BlockState cfj1, final Level bqb, final BlockPos fu, final BlockState cfj4, final boolean boolean5) {
        if (boolean5) {
            return;
        }
        super.onRemove(cfj1, bqb, fu, cfj4, boolean5);
        if (cfj1.<RailShape>getValue(this.getShapeProperty()).isAscending()) {
            bqb.updateNeighborsAt(fu.above(), this);
        }
        if (this.isStraight) {
            bqb.updateNeighborsAt(fu, this);
            bqb.updateNeighborsAt(fu.below(), this);
        }
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bin) {
        final BlockState cfj3 = super.defaultBlockState();
        final Direction fz4 = bin.getHorizontalDirection();
        final boolean boolean5 = fz4 == Direction.EAST || fz4 == Direction.WEST;
        return ((StateHolder<O, BlockState>)cfj3).<RailShape, RailShape>setValue(this.getShapeProperty(), boolean5 ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH);
    }
    
    public abstract Property<RailShape> getShapeProperty();
    
    static {
        FLAT_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 2.0, 16.0);
        HALF_BLOCK_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 8.0, 16.0);
    }
}
