package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.phys.shapes.Shapes;
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.PushReaction;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.sounds.SoundSource;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.level.block.entity.BellBlockEntity;
import net.minecraft.stats.Stats;
import javax.annotation.Nullable;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
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.state.BlockBehaviour;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.BellAttachType;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;

public class BellBlock extends BaseEntityBlock {
    public static final DirectionProperty FACING;
    public static final EnumProperty<BellAttachType> ATTACHMENT;
    public static final BooleanProperty POWERED;
    private static final VoxelShape NORTH_SOUTH_FLOOR_SHAPE;
    private static final VoxelShape EAST_WEST_FLOOR_SHAPE;
    private static final VoxelShape BELL_TOP_SHAPE;
    private static final VoxelShape BELL_BOTTOM_SHAPE;
    private static final VoxelShape BELL_SHAPE;
    private static final VoxelShape NORTH_SOUTH_BETWEEN;
    private static final VoxelShape EAST_WEST_BETWEEN;
    private static final VoxelShape TO_WEST;
    private static final VoxelShape TO_EAST;
    private static final VoxelShape TO_NORTH;
    private static final VoxelShape TO_SOUTH;
    private static final VoxelShape CEILING_SHAPE;
    
    public BellBlock(final Properties c) {
        super(c);
        this.registerDefaultState(((((StateHolder<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)BellBlock.FACING, Direction.NORTH)).setValue(BellBlock.ATTACHMENT, BellAttachType.FLOOR)).<Comparable, Boolean>setValue((Property<Comparable>)BellBlock.POWERED, false));
    }
    
    @Override
    public void neighborChanged(final BlockState cfj, final Level bqb, final BlockPos fu3, final Block bvr, final BlockPos fu5, final boolean boolean6) {
        final boolean boolean7 = bqb.hasNeighborSignal(fu3);
        if (boolean7 != cfj.<Boolean>getValue((Property<Boolean>)BellBlock.POWERED)) {
            if (boolean7) {
                this.attemptToRing(bqb, fu3, null);
            }
            bqb.setBlock(fu3, ((StateHolder<O, BlockState>)cfj).<Comparable, Boolean>setValue((Property<Comparable>)BellBlock.POWERED, boolean7), 3);
        }
    }
    
    @Override
    public void onProjectileHit(final Level bqb, final BlockState cfj, final BlockHitResult deh, final Projectile bes) {
        final Entity aom6 = bes.getOwner();
        final Player bec7 = (aom6 instanceof Player) ? ((Player)aom6) : null;
        this.onHit(bqb, cfj, deh, bec7, true);
    }
    
    @Override
    public InteractionResult use(final BlockState cfj, final Level bqb, final BlockPos fu, final Player bec, final InteractionHand anf, final BlockHitResult deh) {
        return this.onHit(bqb, cfj, deh, bec, true) ? InteractionResult.sidedSuccess(bqb.isClientSide) : InteractionResult.PASS;
    }
    
    public boolean onHit(final Level bqb, final BlockState cfj, final BlockHitResult deh, @Nullable final Player bec, final boolean boolean5) {
        final Direction fz7 = deh.getDirection();
        final BlockPos fu8 = deh.getBlockPos();
        final boolean boolean6 = !boolean5 || this.isProperHit(cfj, fz7, deh.getLocation().y - fu8.getY());
        if (boolean6) {
            final boolean boolean7 = this.attemptToRing(bqb, fu8, fz7);
            if (boolean7 && bec != null) {
                bec.awardStat(Stats.BELL_RING);
            }
            return true;
        }
        return false;
    }
    
    private boolean isProperHit(final BlockState cfj, final Direction fz, final double double3) {
        if (fz.getAxis() == Direction.Axis.Y || double3 > 0.8123999834060669) {
            return false;
        }
        final Direction fz2 = cfj.<Direction>getValue((Property<Direction>)BellBlock.FACING);
        final BellAttachType cfy7 = cfj.<BellAttachType>getValue(BellBlock.ATTACHMENT);
        switch (cfy7) {
            case FLOOR: {
                return fz2.getAxis() == fz.getAxis();
            }
            case SINGLE_WALL:
            case DOUBLE_WALL: {
                return fz2.getAxis() != fz.getAxis();
            }
            case CEILING: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    
    public boolean attemptToRing(final Level bqb, final BlockPos fu, @Nullable Direction fz) {
        final BlockEntity cdl5 = bqb.getBlockEntity(fu);
        if (!bqb.isClientSide && cdl5 instanceof BellBlockEntity) {
            if (fz == null) {
                fz = bqb.getBlockState(fu).<Direction>getValue((Property<Direction>)BellBlock.FACING);
            }
            ((BellBlockEntity)cdl5).onHit(fz);
            bqb.playSound(null, fu, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0f, 1.0f);
            return true;
        }
        return false;
    }
    
    private VoxelShape getVoxelShape(final BlockState cfj) {
        final Direction fz3 = cfj.<Direction>getValue((Property<Direction>)BellBlock.FACING);
        final BellAttachType cfy4 = cfj.<BellAttachType>getValue(BellBlock.ATTACHMENT);
        if (cfy4 == BellAttachType.FLOOR) {
            if (fz3 == Direction.NORTH || fz3 == Direction.SOUTH) {
                return BellBlock.NORTH_SOUTH_FLOOR_SHAPE;
            }
            return BellBlock.EAST_WEST_FLOOR_SHAPE;
        }
        else {
            if (cfy4 == BellAttachType.CEILING) {
                return BellBlock.CEILING_SHAPE;
            }
            if (cfy4 == BellAttachType.DOUBLE_WALL) {
                if (fz3 == Direction.NORTH || fz3 == Direction.SOUTH) {
                    return BellBlock.NORTH_SOUTH_BETWEEN;
                }
                return BellBlock.EAST_WEST_BETWEEN;
            }
            else {
                if (fz3 == Direction.NORTH) {
                    return BellBlock.TO_NORTH;
                }
                if (fz3 == Direction.SOUTH) {
                    return BellBlock.TO_SOUTH;
                }
                if (fz3 == Direction.EAST) {
                    return BellBlock.TO_EAST;
                }
                return BellBlock.TO_WEST;
            }
        }
    }
    
    @Override
    public VoxelShape getCollisionShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return this.getVoxelShape(cfj);
    }
    
    @Override
    public VoxelShape getShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return this.getVoxelShape(cfj);
    }
    
    @Override
    public RenderShape getRenderShape(final BlockState cfj) {
        return RenderShape.MODEL;
    }
    
    @Nullable
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bin) {
        final Direction fz4 = bin.getClickedFace();
        final BlockPos fu5 = bin.getClickedPos();
        final Level bqb6 = bin.getLevel();
        final Direction.Axis a7 = fz4.getAxis();
        if (a7 == Direction.Axis.Y) {
            final BlockState cfj3 = (((StateHolder<O, BlockState>)this.defaultBlockState()).setValue(BellBlock.ATTACHMENT, (fz4 == Direction.DOWN) ? BellAttachType.CEILING : BellAttachType.FLOOR)).<Comparable, Direction>setValue((Property<Comparable>)BellBlock.FACING, bin.getHorizontalDirection());
            if (cfj3.canSurvive(bin.getLevel(), fu5)) {
                return cfj3;
            }
        }
        else {
            final boolean boolean8 = (a7 == Direction.Axis.X && bqb6.getBlockState(fu5.west()).isFaceSturdy(bqb6, fu5.west(), Direction.EAST) && bqb6.getBlockState(fu5.east()).isFaceSturdy(bqb6, fu5.east(), Direction.WEST)) || (a7 == Direction.Axis.Z && bqb6.getBlockState(fu5.north()).isFaceSturdy(bqb6, fu5.north(), Direction.SOUTH) && bqb6.getBlockState(fu5.south()).isFaceSturdy(bqb6, fu5.south(), Direction.NORTH));
            BlockState cfj3 = (((StateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)BellBlock.FACING, fz4.getOpposite())).<BellAttachType, BellAttachType>setValue(BellBlock.ATTACHMENT, boolean8 ? BellAttachType.DOUBLE_WALL : BellAttachType.SINGLE_WALL);
            if (cfj3.canSurvive(bin.getLevel(), bin.getClickedPos())) {
                return cfj3;
            }
            final boolean boolean9 = bqb6.getBlockState(fu5.below()).isFaceSturdy(bqb6, fu5.below(), Direction.UP);
            cfj3 = ((StateHolder<O, BlockState>)cfj3).<BellAttachType, BellAttachType>setValue(BellBlock.ATTACHMENT, boolean9 ? BellAttachType.FLOOR : BellAttachType.CEILING);
            if (cfj3.canSurvive(bin.getLevel(), bin.getClickedPos())) {
                return cfj3;
            }
        }
        return null;
    }
    
    @Override
    public BlockState updateShape(final BlockState cfj1, final Direction fz, final BlockState cfj3, final LevelAccessor bqc, final BlockPos fu5, final BlockPos fu6) {
        final BellAttachType cfy8 = cfj1.<BellAttachType>getValue(BellBlock.ATTACHMENT);
        final Direction fz2 = getConnectedDirection(cfj1).getOpposite();
        if (fz2 == fz && !cfj1.canSurvive(bqc, fu5) && cfy8 != BellAttachType.DOUBLE_WALL) {
            return Blocks.AIR.defaultBlockState();
        }
        if (fz.getAxis() == cfj1.<Direction>getValue((Property<Direction>)BellBlock.FACING).getAxis()) {
            if (cfy8 == BellAttachType.DOUBLE_WALL && !cfj3.isFaceSturdy(bqc, fu6, fz)) {
                return (((StateHolder<O, BlockState>)cfj1).setValue(BellBlock.ATTACHMENT, BellAttachType.SINGLE_WALL)).<Comparable, Direction>setValue((Property<Comparable>)BellBlock.FACING, fz.getOpposite());
            }
            if (cfy8 == BellAttachType.SINGLE_WALL && fz2.getOpposite() == fz && cfj3.isFaceSturdy(bqc, fu6, cfj1.<Direction>getValue((Property<Direction>)BellBlock.FACING))) {
                return ((StateHolder<O, BlockState>)cfj1).<BellAttachType, BellAttachType>setValue(BellBlock.ATTACHMENT, BellAttachType.DOUBLE_WALL);
            }
        }
        return super.updateShape(cfj1, fz, cfj3, bqc, fu5, fu6);
    }
    
    @Override
    public boolean canSurvive(final BlockState cfj, final LevelReader bqd, final BlockPos fu) {
        final Direction fz5 = getConnectedDirection(cfj).getOpposite();
        if (fz5 == Direction.UP) {
            return Block.canSupportCenter(bqd, fu.above(), Direction.DOWN);
        }
        return FaceAttachedHorizontalDirectionalBlock.canAttach(bqd, fu, fz5);
    }
    
    private static Direction getConnectedDirection(final BlockState cfj) {
        switch (cfj.<BellAttachType>getValue(BellBlock.ATTACHMENT)) {
            case CEILING: {
                return Direction.DOWN;
            }
            case FLOOR: {
                return Direction.UP;
            }
            default: {
                return cfj.<Direction>getValue((Property<Direction>)BellBlock.FACING).getOpposite();
            }
        }
    }
    
    @Override
    public PushReaction getPistonPushReaction(final BlockState cfj) {
        return PushReaction.DESTROY;
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(BellBlock.FACING, BellBlock.ATTACHMENT, BellBlock.POWERED);
    }
    
    @Nullable
    @Override
    public BlockEntity newBlockEntity(final BlockGetter bpg) {
        return new BellBlockEntity();
    }
    
    @Override
    public boolean isPathfindable(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final PathComputationType czg) {
        return false;
    }
    
    static {
        FACING = HorizontalDirectionalBlock.FACING;
        ATTACHMENT = BlockStateProperties.BELL_ATTACHMENT;
        POWERED = BlockStateProperties.POWERED;
        NORTH_SOUTH_FLOOR_SHAPE = Block.box(0.0, 0.0, 4.0, 16.0, 16.0, 12.0);
        EAST_WEST_FLOOR_SHAPE = Block.box(4.0, 0.0, 0.0, 12.0, 16.0, 16.0);
        BELL_TOP_SHAPE = Block.box(5.0, 6.0, 5.0, 11.0, 13.0, 11.0);
        BELL_BOTTOM_SHAPE = Block.box(4.0, 4.0, 4.0, 12.0, 6.0, 12.0);
        BELL_SHAPE = Shapes.or(BellBlock.BELL_BOTTOM_SHAPE, BellBlock.BELL_TOP_SHAPE);
        NORTH_SOUTH_BETWEEN = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0, 13.0, 0.0, 9.0, 15.0, 16.0));
        EAST_WEST_BETWEEN = Shapes.or(BellBlock.BELL_SHAPE, Block.box(0.0, 13.0, 7.0, 16.0, 15.0, 9.0));
        TO_WEST = Shapes.or(BellBlock.BELL_SHAPE, Block.box(0.0, 13.0, 7.0, 13.0, 15.0, 9.0));
        TO_EAST = Shapes.or(BellBlock.BELL_SHAPE, Block.box(3.0, 13.0, 7.0, 16.0, 15.0, 9.0));
        TO_NORTH = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0, 13.0, 0.0, 9.0, 15.0, 13.0));
        TO_SOUTH = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0, 13.0, 3.0, 9.0, 15.0, 16.0));
        CEILING_SHAPE = Shapes.or(BellBlock.BELL_SHAPE, Block.box(7.0, 13.0, 7.0, 9.0, 16.0, 9.0));
    }
}
