package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.AbstractStateHolder;
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.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.entity.Entity;
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.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;
    private 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(((((AbstractStateHolder<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 byj, final Level bjw, final BlockPos fk3, final Block bph, final BlockPos fk5, final boolean boolean6) {
        final boolean boolean7 = bjw.hasNeighborSignal(fk3);
        if (boolean7 != byj.<Boolean>getValue((Property<Boolean>)BellBlock.POWERED)) {
            if (boolean7) {
                this.attemptToRing(bjw, fk3, null);
            }
            bjw.setBlock(fk3, ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Boolean>setValue((Property<Comparable>)BellBlock.POWERED, boolean7), 3);
        }
    }
    
    @Override
    public void onProjectileHit(final Level bjw, final BlockState byj, final BlockHitResult cvg, final Entity akq) {
        if (akq instanceof AbstractArrow) {
            final Entity akq2 = ((AbstractArrow)akq).getOwner();
            final Player ayj7 = (akq2 instanceof Player) ? ((Player)akq2) : null;
            this.onHit(bjw, byj, cvg, ayj7, true);
        }
    }
    
    @Override
    public InteractionResult use(final BlockState byj, final Level bjw, final BlockPos fk, final Player ayj, final InteractionHand ajk, final BlockHitResult cvg) {
        return this.onHit(bjw, byj, cvg, ayj, true) ? InteractionResult.SUCCESS : InteractionResult.PASS;
    }
    
    public boolean onHit(final Level bjw, final BlockState byj, final BlockHitResult cvg, @Nullable final Player ayj, final boolean boolean5) {
        final Direction fp7 = cvg.getDirection();
        final BlockPos fk8 = cvg.getBlockPos();
        final boolean boolean6 = !boolean5 || this.isProperHit(byj, fp7, cvg.getLocation().y - fk8.getY());
        if (boolean6) {
            final boolean boolean7 = this.attemptToRing(bjw, fk8, fp7);
            if (boolean7 && ayj != null) {
                ayj.awardStat(Stats.BELL_RING);
            }
            return true;
        }
        return false;
    }
    
    private boolean isProperHit(final BlockState byj, final Direction fp, final double double3) {
        if (fp.getAxis() == Direction.Axis.Y || double3 > 0.8123999834060669) {
            return false;
        }
        final Direction fp2 = byj.<Direction>getValue((Property<Direction>)BellBlock.FACING);
        final BellAttachType byz7 = byj.<BellAttachType>getValue(BellBlock.ATTACHMENT);
        switch (byz7) {
            case FLOOR: {
                return fp2.getAxis() == fp.getAxis();
            }
            case SINGLE_WALL:
            case DOUBLE_WALL: {
                return fp2.getAxis() != fp.getAxis();
            }
            case CEILING: {
                return true;
            }
            default: {
                return false;
            }
        }
    }
    
    public boolean attemptToRing(final Level bjw, final BlockPos fk, @Nullable Direction fp) {
        final BlockEntity bwl5 = bjw.getBlockEntity(fk);
        if (!bjw.isClientSide && bwl5 instanceof BellBlockEntity) {
            if (fp == null) {
                fp = bjw.getBlockState(fk).<Direction>getValue((Property<Direction>)BellBlock.FACING);
            }
            ((BellBlockEntity)bwl5).onHit(fp);
            bjw.playSound(null, fk, SoundEvents.BELL_BLOCK, SoundSource.BLOCKS, 2.0f, 1.0f);
            return true;
        }
        return false;
    }
    
    private VoxelShape getVoxelShape(final BlockState byj) {
        final Direction fp3 = byj.<Direction>getValue((Property<Direction>)BellBlock.FACING);
        final BellAttachType byz4 = byj.<BellAttachType>getValue(BellBlock.ATTACHMENT);
        if (byz4 == BellAttachType.FLOOR) {
            if (fp3 == Direction.NORTH || fp3 == Direction.SOUTH) {
                return BellBlock.NORTH_SOUTH_FLOOR_SHAPE;
            }
            return BellBlock.EAST_WEST_FLOOR_SHAPE;
        }
        else {
            if (byz4 == BellAttachType.CEILING) {
                return BellBlock.CEILING_SHAPE;
            }
            if (byz4 == BellAttachType.DOUBLE_WALL) {
                if (fp3 == Direction.NORTH || fp3 == Direction.SOUTH) {
                    return BellBlock.NORTH_SOUTH_BETWEEN;
                }
                return BellBlock.EAST_WEST_BETWEEN;
            }
            else {
                if (fp3 == Direction.NORTH) {
                    return BellBlock.TO_NORTH;
                }
                if (fp3 == Direction.SOUTH) {
                    return BellBlock.TO_SOUTH;
                }
                if (fp3 == Direction.EAST) {
                    return BellBlock.TO_EAST;
                }
                return BellBlock.TO_WEST;
            }
        }
    }
    
    @Override
    public VoxelShape getCollisionShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        return this.getVoxelShape(byj);
    }
    
    @Override
    public VoxelShape getShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        return this.getVoxelShape(byj);
    }
    
    @Override
    public RenderShape getRenderShape(final BlockState byj) {
        return RenderShape.MODEL;
    }
    
    @Nullable
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bcq) {
        final Direction fp4 = bcq.getClickedFace();
        final BlockPos fk5 = bcq.getClickedPos();
        final Level bjw6 = bcq.getLevel();
        final Direction.Axis a7 = fp4.getAxis();
        if (a7 == Direction.Axis.Y) {
            final BlockState byj3 = (((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).setValue(BellBlock.ATTACHMENT, (fp4 == Direction.DOWN) ? BellAttachType.CEILING : BellAttachType.FLOOR)).<Comparable, Direction>setValue((Property<Comparable>)BellBlock.FACING, bcq.getHorizontalDirection());
            if (byj3.canSurvive(bcq.getLevel(), fk5)) {
                return byj3;
            }
        }
        else {
            final boolean boolean8 = (a7 == Direction.Axis.X && bjw6.getBlockState(fk5.west()).isFaceSturdy(bjw6, fk5.west(), Direction.EAST) && bjw6.getBlockState(fk5.east()).isFaceSturdy(bjw6, fk5.east(), Direction.WEST)) || (a7 == Direction.Axis.Z && bjw6.getBlockState(fk5.north()).isFaceSturdy(bjw6, fk5.north(), Direction.SOUTH) && bjw6.getBlockState(fk5.south()).isFaceSturdy(bjw6, fk5.south(), Direction.NORTH));
            BlockState byj3 = (((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)BellBlock.FACING, fp4.getOpposite())).<BellAttachType, BellAttachType>setValue(BellBlock.ATTACHMENT, boolean8 ? BellAttachType.DOUBLE_WALL : BellAttachType.SINGLE_WALL);
            if (byj3.canSurvive(bcq.getLevel(), bcq.getClickedPos())) {
                return byj3;
            }
            final boolean boolean9 = bjw6.getBlockState(fk5.below()).isFaceSturdy(bjw6, fk5.below(), Direction.UP);
            byj3 = ((AbstractStateHolder<O, BlockState>)byj3).<BellAttachType, BellAttachType>setValue(BellBlock.ATTACHMENT, boolean9 ? BellAttachType.FLOOR : BellAttachType.CEILING);
            if (byj3.canSurvive(bcq.getLevel(), bcq.getClickedPos())) {
                return byj3;
            }
        }
        return null;
    }
    
    @Override
    public BlockState updateShape(final BlockState byj1, final Direction fp, final BlockState byj3, final LevelAccessor bjx, final BlockPos fk5, final BlockPos fk6) {
        final BellAttachType byz8 = byj1.<BellAttachType>getValue(BellBlock.ATTACHMENT);
        final Direction fp2 = getConnectedDirection(byj1).getOpposite();
        if (fp2 == fp && !byj1.canSurvive(bjx, fk5) && byz8 != BellAttachType.DOUBLE_WALL) {
            return Blocks.AIR.defaultBlockState();
        }
        if (fp.getAxis() == byj1.<Direction>getValue((Property<Direction>)BellBlock.FACING).getAxis()) {
            if (byz8 == BellAttachType.DOUBLE_WALL && !byj3.isFaceSturdy(bjx, fk6, fp)) {
                return (((AbstractStateHolder<O, BlockState>)byj1).setValue(BellBlock.ATTACHMENT, BellAttachType.SINGLE_WALL)).<Comparable, Direction>setValue((Property<Comparable>)BellBlock.FACING, fp.getOpposite());
            }
            if (byz8 == BellAttachType.SINGLE_WALL && fp2.getOpposite() == fp && byj3.isFaceSturdy(bjx, fk6, byj1.<Direction>getValue((Property<Direction>)BellBlock.FACING))) {
                return ((AbstractStateHolder<O, BlockState>)byj1).<BellAttachType, BellAttachType>setValue(BellBlock.ATTACHMENT, BellAttachType.DOUBLE_WALL);
            }
        }
        return super.updateShape(byj1, fp, byj3, bjx, fk5, fk6);
    }
    
    @Override
    public boolean canSurvive(final BlockState byj, final LevelReader bjz, final BlockPos fk) {
        return FaceAttachedHorizontalDirectionalBlock.canAttach(bjz, fk, getConnectedDirection(byj).getOpposite());
    }
    
    private static Direction getConnectedDirection(final BlockState byj) {
        switch (byj.<BellAttachType>getValue(BellBlock.ATTACHMENT)) {
            case CEILING: {
                return Direction.DOWN;
            }
            case FLOOR: {
                return Direction.UP;
            }
            default: {
                return byj.<Direction>getValue((Property<Direction>)BellBlock.FACING).getOpposite();
            }
        }
    }
    
    @Override
    public PushReaction getPistonPushReaction(final BlockState byj) {
        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 bjg) {
        return new BellBlockEntity();
    }
    
    @Override
    public boolean isPathfindable(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final PathComputationType cqr) {
        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));
    }
}
