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.phys.shapes.BooleanOp;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.tags.Tag;
import net.minecraft.tags.BlockTags;
import net.minecraft.core.Direction;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import java.util.Iterator;
import com.google.common.collect.ImmutableMap;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Map;
import net.minecraft.world.level.block.state.properties.WallSide;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.BooleanProperty;

public class WallBlock extends Block implements SimpleWaterloggedBlock {
    public static final BooleanProperty UP;
    public static final EnumProperty<WallSide> EAST_WALL;
    public static final EnumProperty<WallSide> NORTH_WALL;
    public static final EnumProperty<WallSide> SOUTH_WALL;
    public static final EnumProperty<WallSide> WEST_WALL;
    public static final BooleanProperty WATERLOGGED;
    private final Map<BlockState, VoxelShape> shapeByIndex;
    private final Map<BlockState, VoxelShape> collisionShapeByIndex;
    private static final VoxelShape POST_TEST;
    private static final VoxelShape NORTH_TEST;
    private static final VoxelShape SOUTH_TEST;
    private static final VoxelShape WEST_TEST;
    private static final VoxelShape EAST_TEST;
    
    public WallBlock(final Properties c) {
        super(c);
        this.registerDefaultState((((((((StateHolder<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)WallBlock.UP, true)).setValue(WallBlock.NORTH_WALL, WallSide.NONE)).setValue(WallBlock.EAST_WALL, WallSide.NONE)).setValue(WallBlock.SOUTH_WALL, WallSide.NONE)).setValue(WallBlock.WEST_WALL, WallSide.NONE)).<Comparable, Boolean>setValue((Property<Comparable>)WallBlock.WATERLOGGED, false));
        this.shapeByIndex = this.makeShapes(4.0f, 3.0f, 16.0f, 0.0f, 14.0f, 16.0f);
        this.collisionShapeByIndex = this.makeShapes(4.0f, 3.0f, 24.0f, 0.0f, 24.0f, 24.0f);
    }
    
    private static VoxelShape applyWallShape(final VoxelShape dfg1, final WallSide cgr, final VoxelShape dfg3, final VoxelShape dfg4) {
        if (cgr == WallSide.TALL) {
            return Shapes.or(dfg1, dfg4);
        }
        if (cgr == WallSide.LOW) {
            return Shapes.or(dfg1, dfg3);
        }
        return dfg1;
    }
    
    private Map<BlockState, VoxelShape> makeShapes(final float float1, final float float2, final float float3, final float float4, final float float5, final float float6) {
        final float float7 = 8.0f - float1;
        final float float8 = 8.0f + float1;
        final float float9 = 8.0f - float2;
        final float float10 = 8.0f + float2;
        final VoxelShape dfg12 = Block.box(float7, 0.0, float7, float8, float3, float8);
        final VoxelShape dfg13 = Block.box(float9, float4, 0.0, float10, float5, float10);
        final VoxelShape dfg14 = Block.box(float9, float4, float9, float10, float5, 16.0);
        final VoxelShape dfg15 = Block.box(0.0, float4, float9, float10, float5, float10);
        final VoxelShape dfg16 = Block.box(float9, float4, float9, 16.0, float5, float10);
        final VoxelShape dfg17 = Block.box(float9, float4, 0.0, float10, float6, float10);
        final VoxelShape dfg18 = Block.box(float9, float4, float9, float10, float6, 16.0);
        final VoxelShape dfg19 = Block.box(0.0, float4, float9, float10, float6, float10);
        final VoxelShape dfg20 = Block.box(float9, float4, float9, 16.0, float6, float10);
        final ImmutableMap.Builder<BlockState, VoxelShape> builder21 = ImmutableMap.<BlockState, VoxelShape>builder();
        for (final Boolean boolean23 : WallBlock.UP.getPossibleValues()) {
            for (final WallSide cgr25 : WallBlock.EAST_WALL.getPossibleValues()) {
                for (final WallSide cgr26 : WallBlock.NORTH_WALL.getPossibleValues()) {
                    for (final WallSide cgr27 : WallBlock.WEST_WALL.getPossibleValues()) {
                        for (final WallSide cgr28 : WallBlock.SOUTH_WALL.getPossibleValues()) {
                            VoxelShape dfg21 = Shapes.empty();
                            dfg21 = applyWallShape(dfg21, cgr25, dfg16, dfg20);
                            dfg21 = applyWallShape(dfg21, cgr27, dfg15, dfg19);
                            dfg21 = applyWallShape(dfg21, cgr26, dfg13, dfg17);
                            dfg21 = applyWallShape(dfg21, cgr28, dfg14, dfg18);
                            if (boolean23) {
                                dfg21 = Shapes.or(dfg21, dfg12);
                            }
                            final BlockState cfj33 = ((((((StateHolder<O, BlockState>)this.defaultBlockState()).setValue((Property<Comparable>)WallBlock.UP, boolean23)).setValue(WallBlock.EAST_WALL, cgr25)).setValue(WallBlock.WEST_WALL, cgr27)).setValue(WallBlock.NORTH_WALL, cgr26)).<WallSide, WallSide>setValue(WallBlock.SOUTH_WALL, cgr28);
                            builder21.put(((StateHolder<O, BlockState>)cfj33).<Comparable, Boolean>setValue((Property<Comparable>)WallBlock.WATERLOGGED, false), dfg21);
                            builder21.put(((StateHolder<O, BlockState>)cfj33).<Comparable, Boolean>setValue((Property<Comparable>)WallBlock.WATERLOGGED, true), dfg21);
                        }
                    }
                }
            }
        }
        return builder21.build();
    }
    
    @Override
    public VoxelShape getShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return this.shapeByIndex.get(cfj);
    }
    
    @Override
    public VoxelShape getCollisionShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return this.collisionShapeByIndex.get(cfj);
    }
    
    @Override
    public boolean isPathfindable(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final PathComputationType czg) {
        return false;
    }
    
    private boolean connectsTo(final BlockState cfj, final boolean boolean2, final Direction fz) {
        final Block bvr5 = cfj.getBlock();
        final boolean boolean3 = bvr5 instanceof FenceGateBlock && FenceGateBlock.connectsToDirection(cfj, fz);
        return cfj.is(BlockTags.WALLS) || (!Block.isExceptionForConnection(bvr5) && boolean2) || bvr5 instanceof IronBarsBlock || boolean3;
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bin) {
        final LevelReader bqd3 = bin.getLevel();
        final BlockPos fu4 = bin.getClickedPos();
        final FluidState cxa5 = bin.getLevel().getFluidState(bin.getClickedPos());
        final BlockPos fu5 = fu4.north();
        final BlockPos fu6 = fu4.east();
        final BlockPos fu7 = fu4.south();
        final BlockPos fu8 = fu4.west();
        final BlockPos fu9 = fu4.above();
        final BlockState cfj11 = bqd3.getBlockState(fu5);
        final BlockState cfj12 = bqd3.getBlockState(fu6);
        final BlockState cfj13 = bqd3.getBlockState(fu7);
        final BlockState cfj14 = bqd3.getBlockState(fu8);
        final BlockState cfj15 = bqd3.getBlockState(fu9);
        final boolean boolean16 = this.connectsTo(cfj11, cfj11.isFaceSturdy(bqd3, fu5, Direction.SOUTH), Direction.SOUTH);
        final boolean boolean17 = this.connectsTo(cfj12, cfj12.isFaceSturdy(bqd3, fu6, Direction.WEST), Direction.WEST);
        final boolean boolean18 = this.connectsTo(cfj13, cfj13.isFaceSturdy(bqd3, fu7, Direction.NORTH), Direction.NORTH);
        final boolean boolean19 = this.connectsTo(cfj14, cfj14.isFaceSturdy(bqd3, fu8, Direction.EAST), Direction.EAST);
        final BlockState cfj16 = ((StateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Boolean>setValue((Property<Comparable>)WallBlock.WATERLOGGED, cxa5.getType() == Fluids.WATER);
        return this.updateShape(bqd3, cfj16, fu9, cfj15, boolean16, boolean17, boolean18, boolean19);
    }
    
    @Override
    public BlockState updateShape(final BlockState cfj1, final Direction fz, final BlockState cfj3, final LevelAccessor bqc, final BlockPos fu5, final BlockPos fu6) {
        if (cfj1.<Boolean>getValue((Property<Boolean>)WallBlock.WATERLOGGED)) {
            bqc.getLiquidTicks().scheduleTick(fu5, Fluids.WATER, Fluids.WATER.getTickDelay(bqc));
        }
        if (fz == Direction.DOWN) {
            return super.updateShape(cfj1, fz, cfj3, bqc, fu5, fu6);
        }
        if (fz == Direction.UP) {
            return this.topUpdate(bqc, cfj1, fu6, cfj3);
        }
        return this.sideUpdate(bqc, fu5, cfj1, fu6, cfj3, fz);
    }
    
    private static boolean isConnected(final BlockState cfj, final Property<WallSide> cgl) {
        return cfj.<WallSide>getValue(cgl) != WallSide.NONE;
    }
    
    private static boolean isCovered(final VoxelShape dfg1, final VoxelShape dfg2) {
        return !Shapes.joinIsNotEmpty(dfg2, dfg1, BooleanOp.ONLY_FIRST);
    }
    
    private BlockState topUpdate(final LevelReader bqd, final BlockState cfj2, final BlockPos fu, final BlockState cfj4) {
        final boolean boolean6 = isConnected(cfj2, WallBlock.NORTH_WALL);
        final boolean boolean7 = isConnected(cfj2, WallBlock.EAST_WALL);
        final boolean boolean8 = isConnected(cfj2, WallBlock.SOUTH_WALL);
        final boolean boolean9 = isConnected(cfj2, WallBlock.WEST_WALL);
        return this.updateShape(bqd, cfj2, fu, cfj4, boolean6, boolean7, boolean8, boolean9);
    }
    
    private BlockState sideUpdate(final LevelReader bqd, final BlockPos fu2, final BlockState cfj3, final BlockPos fu4, final BlockState cfj5, final Direction fz) {
        final Direction fz2 = fz.getOpposite();
        final boolean boolean9 = (fz == Direction.NORTH) ? this.connectsTo(cfj5, cfj5.isFaceSturdy(bqd, fu4, fz2), fz2) : isConnected(cfj3, WallBlock.NORTH_WALL);
        final boolean boolean10 = (fz == Direction.EAST) ? this.connectsTo(cfj5, cfj5.isFaceSturdy(bqd, fu4, fz2), fz2) : isConnected(cfj3, WallBlock.EAST_WALL);
        final boolean boolean11 = (fz == Direction.SOUTH) ? this.connectsTo(cfj5, cfj5.isFaceSturdy(bqd, fu4, fz2), fz2) : isConnected(cfj3, WallBlock.SOUTH_WALL);
        final boolean boolean12 = (fz == Direction.WEST) ? this.connectsTo(cfj5, cfj5.isFaceSturdy(bqd, fu4, fz2), fz2) : isConnected(cfj3, WallBlock.WEST_WALL);
        final BlockPos fu5 = fu2.above();
        final BlockState cfj6 = bqd.getBlockState(fu5);
        return this.updateShape(bqd, cfj3, fu5, cfj6, boolean9, boolean10, boolean11, boolean12);
    }
    
    private BlockState updateShape(final LevelReader bqd, final BlockState cfj2, final BlockPos fu, final BlockState cfj4, final boolean boolean5, final boolean boolean6, final boolean boolean7, final boolean boolean8) {
        final VoxelShape dfg10 = cfj4.getCollisionShape(bqd, fu).getFaceShape(Direction.DOWN);
        final BlockState cfj5 = this.updateSides(cfj2, boolean5, boolean6, boolean7, boolean8, dfg10);
        return ((StateHolder<O, BlockState>)cfj5).<Comparable, Boolean>setValue((Property<Comparable>)WallBlock.UP, this.shouldRaisePost(cfj5, cfj4, dfg10));
    }
    
    private boolean shouldRaisePost(final BlockState cfj1, final BlockState cfj2, final VoxelShape dfg) {
        final boolean boolean5 = cfj2.getBlock() instanceof WallBlock && cfj2.<Boolean>getValue((Property<Boolean>)WallBlock.UP);
        if (boolean5) {
            return true;
        }
        final WallSide cgr6 = cfj1.<WallSide>getValue(WallBlock.NORTH_WALL);
        final WallSide cgr7 = cfj1.<WallSide>getValue(WallBlock.SOUTH_WALL);
        final WallSide cgr8 = cfj1.<WallSide>getValue(WallBlock.EAST_WALL);
        final WallSide cgr9 = cfj1.<WallSide>getValue(WallBlock.WEST_WALL);
        final boolean boolean6 = cgr7 == WallSide.NONE;
        final boolean boolean7 = cgr9 == WallSide.NONE;
        final boolean boolean8 = cgr8 == WallSide.NONE;
        final boolean boolean9 = cgr6 == WallSide.NONE;
        final boolean boolean10 = (boolean9 && boolean6 && boolean7 && boolean8) || boolean9 != boolean6 || boolean7 != boolean8;
        if (boolean10) {
            return true;
        }
        final boolean boolean11 = (cgr6 == WallSide.TALL && cgr7 == WallSide.TALL) || (cgr8 == WallSide.TALL && cgr9 == WallSide.TALL);
        return !boolean11 && (cfj2.getBlock().is(BlockTags.WALL_POST_OVERRIDE) || isCovered(dfg, WallBlock.POST_TEST));
    }
    
    private BlockState updateSides(final BlockState cfj, final boolean boolean2, final boolean boolean3, final boolean boolean4, final boolean boolean5, final VoxelShape dfg) {
        return (((((StateHolder<O, BlockState>)cfj).setValue(WallBlock.NORTH_WALL, this.makeWallState(boolean2, dfg, WallBlock.NORTH_TEST))).setValue(WallBlock.EAST_WALL, this.makeWallState(boolean3, dfg, WallBlock.EAST_TEST))).setValue(WallBlock.SOUTH_WALL, this.makeWallState(boolean4, dfg, WallBlock.SOUTH_TEST))).<WallSide, WallSide>setValue(WallBlock.WEST_WALL, this.makeWallState(boolean5, dfg, WallBlock.WEST_TEST));
    }
    
    private WallSide makeWallState(final boolean boolean1, final VoxelShape dfg2, final VoxelShape dfg3) {
        if (!boolean1) {
            return WallSide.NONE;
        }
        if (isCovered(dfg2, dfg3)) {
            return WallSide.TALL;
        }
        return WallSide.LOW;
    }
    
    @Override
    public FluidState getFluidState(final BlockState cfj) {
        if (cfj.<Boolean>getValue((Property<Boolean>)WallBlock.WATERLOGGED)) {
            return Fluids.WATER.getSource(false);
        }
        return super.getFluidState(cfj);
    }
    
    @Override
    public boolean propagatesSkylightDown(final BlockState cfj, final BlockGetter bpg, final BlockPos fu) {
        return !cfj.<Boolean>getValue((Property<Boolean>)WallBlock.WATERLOGGED);
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(WallBlock.UP, WallBlock.NORTH_WALL, WallBlock.EAST_WALL, WallBlock.WEST_WALL, WallBlock.SOUTH_WALL, WallBlock.WATERLOGGED);
    }
    
    @Override
    public BlockState rotate(final BlockState cfj, final Rotation cap) {
        switch (cap) {
            case CLOCKWISE_180: {
                return (((((StateHolder<O, BlockState>)cfj).setValue(WallBlock.NORTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.SOUTH_WALL))).setValue(WallBlock.EAST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.WEST_WALL))).setValue(WallBlock.SOUTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.NORTH_WALL))).<WallSide, Comparable>setValue(WallBlock.WEST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.EAST_WALL));
            }
            case COUNTERCLOCKWISE_90: {
                return (((((StateHolder<O, BlockState>)cfj).setValue(WallBlock.NORTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.EAST_WALL))).setValue(WallBlock.EAST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.SOUTH_WALL))).setValue(WallBlock.SOUTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.WEST_WALL))).<WallSide, Comparable>setValue(WallBlock.WEST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.NORTH_WALL));
            }
            case CLOCKWISE_90: {
                return (((((StateHolder<O, BlockState>)cfj).setValue(WallBlock.NORTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.WEST_WALL))).setValue(WallBlock.EAST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.NORTH_WALL))).setValue(WallBlock.SOUTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.EAST_WALL))).<WallSide, Comparable>setValue(WallBlock.WEST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.SOUTH_WALL));
            }
            default: {
                return cfj;
            }
        }
    }
    
    @Override
    public BlockState mirror(final BlockState cfj, final Mirror bzj) {
        switch (bzj) {
            case LEFT_RIGHT: {
                return (((StateHolder<O, BlockState>)cfj).setValue(WallBlock.NORTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.SOUTH_WALL))).<WallSide, Comparable>setValue(WallBlock.SOUTH_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.NORTH_WALL));
            }
            case FRONT_BACK: {
                return (((StateHolder<O, BlockState>)cfj).setValue(WallBlock.EAST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.WEST_WALL))).<WallSide, Comparable>setValue(WallBlock.WEST_WALL, (Comparable)cfj.<V>getValue((Property<V>)WallBlock.EAST_WALL));
            }
            default: {
                return super.mirror(cfj, bzj);
            }
        }
    }
    
    static {
        UP = BlockStateProperties.UP;
        EAST_WALL = BlockStateProperties.EAST_WALL;
        NORTH_WALL = BlockStateProperties.NORTH_WALL;
        SOUTH_WALL = BlockStateProperties.SOUTH_WALL;
        WEST_WALL = BlockStateProperties.WEST_WALL;
        WATERLOGGED = BlockStateProperties.WATERLOGGED;
        POST_TEST = Block.box(7.0, 0.0, 7.0, 9.0, 16.0, 9.0);
        NORTH_TEST = Block.box(7.0, 0.0, 0.0, 9.0, 16.0, 9.0);
        SOUTH_TEST = Block.box(7.0, 0.0, 7.0, 9.0, 16.0, 16.0);
        WEST_TEST = Block.box(0.0, 0.0, 7.0, 9.0, 16.0, 9.0);
        EAST_TEST = Block.box(7.0, 0.0, 7.0, 16.0, 16.0, 9.0);
    }
}
