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.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.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.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(((((AbstractStateHolder<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 byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        if (byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.IN_WALL)) {
            return (byj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_SHAPE_LOW : FenceGateBlock.Z_SHAPE_LOW;
        }
        return (byj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_SHAPE : FenceGateBlock.Z_SHAPE;
    }
    
    @Override
    public BlockState updateShape(final BlockState byj1, final Direction fp, final BlockState byj3, final LevelAccessor bjx, final BlockPos fk5, final BlockPos fk6) {
        final Direction.Axis a8 = fp.getAxis();
        if (byj1.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getClockWise().getAxis() == a8) {
            final boolean boolean9 = this.isWall(byj3) || this.isWall(bjx.getBlockState(fk5.relative(fp.getOpposite())));
            return ((AbstractStateHolder<O, BlockState>)byj1).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.IN_WALL, boolean9);
        }
        return super.updateShape(byj1, fp, byj3, bjx, fk5, fk6);
    }
    
    @Override
    public VoxelShape getCollisionShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final CollisionContext cvq) {
        if (byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN)) {
            return Shapes.empty();
        }
        return (byj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.Z) ? FenceGateBlock.Z_COLLISION_SHAPE : FenceGateBlock.X_COLLISION_SHAPE;
    }
    
    @Override
    public VoxelShape getOcclusionShape(final BlockState byj, final BlockGetter bjg, final BlockPos fk) {
        if (byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.IN_WALL)) {
            return (byj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_OCCLUSION_SHAPE_LOW : FenceGateBlock.Z_OCCLUSION_SHAPE_LOW;
        }
        return (byj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == Direction.Axis.X) ? FenceGateBlock.X_OCCLUSION_SHAPE : FenceGateBlock.Z_OCCLUSION_SHAPE;
    }
    
    @Override
    public boolean isPathfindable(final BlockState byj, final BlockGetter bjg, final BlockPos fk, final PathComputationType cqr) {
        switch (cqr) {
            case LAND: {
                return byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN);
            }
            case WATER: {
                return false;
            }
            case AIR: {
                return byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN);
            }
            default: {
                return false;
            }
        }
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bcq) {
        final Level bjw3 = bcq.getLevel();
        final BlockPos fk4 = bcq.getClickedPos();
        final boolean boolean5 = bjw3.hasNeighborSignal(fk4);
        final Direction fp6 = bcq.getHorizontalDirection();
        final Direction.Axis a7 = fp6.getAxis();
        final boolean boolean6 = (a7 == Direction.Axis.Z && (this.isWall(bjw3.getBlockState(fk4.west())) || this.isWall(bjw3.getBlockState(fk4.east())))) || (a7 == Direction.Axis.X && (this.isWall(bjw3.getBlockState(fk4.north())) || this.isWall(bjw3.getBlockState(fk4.south()))));
        return (((((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)FenceGateBlock.FACING, fp6)).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 byj) {
        return byj.getBlock().is(BlockTags.WALLS);
    }
    
    @Override
    public InteractionResult use(BlockState byj, final Level bjw, final BlockPos fk, final Player ayj, final InteractionHand ajk, final BlockHitResult cvg) {
        if (byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN)) {
            byj = ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.OPEN, false);
            bjw.setBlock(fk, byj, 10);
        }
        else {
            final Direction fp8 = ayj.getDirection();
            if (byj.<Comparable>getValue((Property<Comparable>)FenceGateBlock.FACING) == fp8.getOpposite()) {
                byj = ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Direction>setValue((Property<Comparable>)FenceGateBlock.FACING, fp8);
            }
            byj = ((AbstractStateHolder<O, BlockState>)byj).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.OPEN, true);
            bjw.setBlock(fk, byj, 10);
        }
        bjw.levelEvent(ayj, ((boolean)byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN)) ? 1008 : 1014, fk, 0);
        return InteractionResult.SUCCESS;
    }
    
    @Override
    public void neighborChanged(final BlockState byj, final Level bjw, final BlockPos fk3, final Block bph, final BlockPos fk5, final boolean boolean6) {
        if (bjw.isClientSide) {
            return;
        }
        final boolean boolean7 = bjw.hasNeighborSignal(fk3);
        if (byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.POWERED) != boolean7) {
            bjw.setBlock(fk3, (((AbstractStateHolder<O, BlockState>)byj).setValue((Property<Comparable>)FenceGateBlock.POWERED, boolean7)).<Comparable, Boolean>setValue((Property<Comparable>)FenceGateBlock.OPEN, boolean7), 2);
            if (byj.<Boolean>getValue((Property<Boolean>)FenceGateBlock.OPEN) != boolean7) {
                bjw.levelEvent(null, boolean7 ? 1008 : 1014, fk3, 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 byj, final Direction fp) {
        return byj.<Direction>getValue((Property<Direction>)FenceGateBlock.FACING).getAxis() == fp.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));
    }
}
