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.block.state.StateDefinition;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Player;
import net.minecraft.tags.Tag;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.Level;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.core.Direction;
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.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;

public class FenceGateBlock extends HorizontalDirectionalBlock {
    public static final BooleanProperty OPEN;
    public static final BooleanProperty POWERED;
    public static final BooleanProperty IN_WALL;
    protected static final VoxelShape Z_SHAPE;
    protected static final VoxelShape X_SHAPE;
    protected static final VoxelShape Z_SHAPE_LOW;
    protected static final VoxelShape X_SHAPE_LOW;
    protected static final VoxelShape Z_COLLISION_SHAPE;
    protected static final VoxelShape X_COLLISION_SHAPE;
    protected static final VoxelShape Z_OCCLUSION_SHAPE;
    protected static final VoxelShape X_OCCLUSION_SHAPE;
    protected static final VoxelShape Z_OCCLUSION_SHAPE_LOW;
    protected static final VoxelShape X_OCCLUSION_SHAPE_LOW;
    
    public FenceGateBlock(final Properties c) {
        super(c);
        this.registerDefaultState(((((StateHolder<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)FenceGateBlock.OPEN, false)).setValue((Property<Comparable>)FenceGateBlock.POWERED, false)).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.IN_WALL, false));
    }
    
    @Override
    public VoxelShape getShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        if (cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.IN_WALL)) {
            return (cfj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_SHAPE_LOW : FenceGateBlock.Z_SHAPE_LOW;
        }
        return (cfj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_SHAPE : FenceGateBlock.Z_SHAPE;
    }
    
    @Override
    public BlockState updateShape(final BlockState cfj1, final Direction fz, final BlockState cfj3, final LevelAccessor bqc, final BlockPos fu5, final BlockPos fu6) {
        final Direction.Axis a8 = fz.getAxis();
        if (cfj1.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getClockWise().getAxis() == a8) {
            final boolean boolean9 = this.isWall(cfj3) || this.isWall(bqc.getBlockState(fu5.relative(fz.getOpposite())));
            return ((StateHolder<O, BlockState>)cfj1).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.IN_WALL, boolean9);
        }
        return super.updateShape(cfj1, fz, cfj3, bqc, fu5, fu6);
    }
    
    @Override
    public VoxelShape getCollisionShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        if (cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN)) {
            return Shapes.empty();
        }
        return (cfj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.Z) ? FenceGateBlock.Z_COLLISION_SHAPE : FenceGateBlock.X_COLLISION_SHAPE;
    }
    
    @Override
    public VoxelShape getOcclusionShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu) {
        if (cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.IN_WALL)) {
            return (cfj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_OCCLUSION_SHAPE_LOW : FenceGateBlock.Z_OCCLUSION_SHAPE_LOW;
        }
        return (cfj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_OCCLUSION_SHAPE : FenceGateBlock.Z_OCCLUSION_SHAPE;
    }
    
    @Override
    public boolean isPathfindable(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final PathComputationType czg) {
        switch (czg) {
            case LAND: {
                return cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN);
            }
            case WATER: {
                return false;
            }
            case AIR: {
                return cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN);
            }
            default: {
                return false;
            }
        }
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bin) {
        final Level bqb3 = bin.getLevel();
        final BlockPos fu4 = bin.getClickedPos();
        final boolean boolean5 = bqb3.hasNeighborSignal(fu4);
        final Direction fz6 = bin.getHorizontalDirection();
        final Direction.Axis a7 = fz6.getAxis();
        final boolean boolean6 = (a7 == Direction.Axis.Z && (this.isWall(bqb3.getBlockState(fu4.west())) || this.isWall(bqb3.getBlockState(fu4.east())))) || (a7 == Direction.Axis.X && (this.isWall(bqb3.getBlockState(fu4.north())) || this.isWall(bqb3.getBlockState(fu4.south()))));
        return (((((StateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)FenceGateBlock.FACING, fz6)).setValue((Property<Comparable>)FenceGateBlock.OPEN, boolean5)).setValue((Property<Comparable>)FenceGateBlock.POWERED, boolean5)).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.IN_WALL, boolean6);
    }
    
    private boolean isWall(final BlockState cfj) {
        return cfj.getBlock().is(BlockTags.WALLS);
    }
    
    @Override
    public InteractionResult use(BlockState cfj, final Level bqb, final BlockPos fu, final Player bec, final InteractionHand anf, final BlockHitResult deh) {
        if (cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN)) {
            cfj = ((StateHolder<O, BlockState>)cfj).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.OPEN, false);
            bqb.setBlock(fu, cfj, 10);
        }
        else {
            final Direction fz8 = bec.getDirection();
            if (cfj.<Comparable>getValue((Property<Comparable>)FenceGateBlock.FACING) == fz8.getOpposite()) {
                cfj = ((StateHolder<O, BlockState>)cfj).<Comparable, Direction>setValue((Property<Comparable>)FenceGateBlock.FACING, fz8);
            }
            cfj = ((StateHolder<O, BlockState>)cfj).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.OPEN, true);
            bqb.setBlock(fu, cfj, 10);
        }
        bqb.levelEvent(bec, ((boolean)cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN)) ? 1008 : 1014, fu, 0);
        return InteractionResult.sidedSuccess(bqb.isClientSide);
    }
    
    @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 boolean boolean7 = bqb.hasNeighborSignal(fu3);
        if (cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.POWERED) != boolean7) {
            bqb.setBlock(fu3, (((StateHolder<O, BlockState>)cfj).setValue((Property<Comparable>)FenceGateBlock.POWERED, boolean7)).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.OPEN, boolean7), 2);
            if (cfj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN) != boolean7) {
                bqb.levelEvent(null, boolean7 ? 1008 : 1014, fu3, 0);
            }
        }
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(FenceGateBlock.FACING, FenceGateBlock.OPEN, FenceGateBlock.POWERED, FenceGateBlock.IN_WALL);
    }
    
    public static boolean connectsToDirection(final BlockState cfj, final Direction fz) {
        return cfj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == fz.getClockWise().getAxis();
    }
    
    static {
        OPEN = BlockStateProperties.OPEN;
        POWERED = BlockStateProperties.POWERED;
        IN_WALL = BlockStateProperties.IN_WALL;
        Z_SHAPE = Block.box(0.0, 0.0, 6.0, 16.0, 16.0, 10.0);
        X_SHAPE = Block.box(6.0, 0.0, 0.0, 10.0, 16.0, 16.0);
        Z_SHAPE_LOW = Block.box(0.0, 0.0, 6.0, 16.0, 13.0, 10.0);
        X_SHAPE_LOW = Block.box(6.0, 0.0, 0.0, 10.0, 13.0, 16.0);
        Z_COLLISION_SHAPE = Block.box(0.0, 0.0, 6.0, 16.0, 24.0, 10.0);
        X_COLLISION_SHAPE = Block.box(6.0, 0.0, 0.0, 10.0, 24.0, 16.0);
        Z_OCCLUSION_SHAPE = Shapes.or(Block.box(0.0, 5.0, 7.0, 2.0, 16.0, 9.0), Block.box(14.0, 5.0, 7.0, 16.0, 16.0, 9.0));
        X_OCCLUSION_SHAPE = Shapes.or(Block.box(7.0, 5.0, 0.0, 9.0, 16.0, 2.0), Block.box(7.0, 5.0, 14.0, 9.0, 16.0, 16.0));
        Z_OCCLUSION_SHAPE_LOW = Shapes.or(Block.box(0.0, 2.0, 7.0, 2.0, 13.0, 9.0), Block.box(14.0, 2.0, 7.0, 16.0, 13.0, 9.0));
        X_OCCLUSION_SHAPE_LOW = Shapes.or(Block.box(7.0, 2.0, 0.0, 9.0, 13.0, 2.0), Block.box(7.0, 2.0, 14.0, 9.0, 13.0, 16.0));
    }
}
