package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
import com.google.common.collect.ImmutableMap;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
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.world.level.block.state.StateDefinition;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.core.particles.DustParticleOptions;
import java.util.Random;
import net.minecraft.util.Mth;
import javax.annotation.Nullable;
import java.util.Set;
import com.google.common.collect.Sets;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.item.BlockPlaceContext;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BlockGetter;
import java.util.Iterator;
import net.minecraft.world.phys.shapes.Shapes;
import com.google.common.collect.UnmodifiableIterator;
import net.minecraft.world.level.block.state.properties.Property;
import com.google.common.collect.Maps;
import net.minecraft.world.level.block.state.BlockBehaviour;
import com.mojang.math.Vector3f;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.core.Direction;
import java.util.Map;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.block.state.properties.RedstoneSide;
import net.minecraft.world.level.block.state.properties.EnumProperty;

public class RedStoneWireBlock extends Block {
    public static final EnumProperty<RedstoneSide> NORTH;
    public static final EnumProperty<RedstoneSide> EAST;
    public static final EnumProperty<RedstoneSide> SOUTH;
    public static final EnumProperty<RedstoneSide> WEST;
    public static final IntegerProperty POWER;
    public static final Map<Direction, EnumProperty<RedstoneSide>> PROPERTY_BY_DIRECTION;
    private static final VoxelShape SHAPE_DOT;
    private static final Map<Direction, VoxelShape> SHAPES_FLOOR;
    private static final Map<Direction, VoxelShape> SHAPES_UP;
    private final Map<BlockState, VoxelShape> SHAPES_CACHE;
    private static final Vector3f[] COLORS;
    private final BlockState crossState;
    private boolean shouldSignal;
    
    public RedStoneWireBlock(final Properties c) {
        super(c);
        this.SHAPES_CACHE = Maps.newHashMap();
        this.shouldSignal = true;
        this.registerDefaultState(((((((StateHolder<O, BlockState>)this.stateDefinition.any()).setValue(RedStoneWireBlock.NORTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.NONE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.NONE)).setValue(RedStoneWireBlock.WEST, RedstoneSide.NONE)).<Comparable, Integer>setValue((Property<Comparable>)RedStoneWireBlock.POWER, 0));
        this.crossState = (((((StateHolder<O, BlockState>)this.defaultBlockState()).setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE)).setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE)).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE);
        for (final BlockState cfj4 : this.getStateDefinition().getPossibleStates()) {
            if (cfj4.<Integer>getValue((Property<Integer>)RedStoneWireBlock.POWER) == 0) {
                this.SHAPES_CACHE.put(cfj4, this.calculateShape(cfj4));
            }
        }
    }
    
    private VoxelShape calculateShape(final BlockState cfj) {
        VoxelShape dfg3 = RedStoneWireBlock.SHAPE_DOT;
        for (final Direction fz5 : Direction.Plane.HORIZONTAL) {
            final RedstoneSide cgn6 = cfj.<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz5));
            if (cgn6 == RedstoneSide.SIDE) {
                dfg3 = Shapes.or(dfg3, RedStoneWireBlock.SHAPES_FLOOR.get(fz5));
            }
            else {
                if (cgn6 != RedstoneSide.UP) {
                    continue;
                }
                dfg3 = Shapes.or(dfg3, RedStoneWireBlock.SHAPES_UP.get(fz5));
            }
        }
        return dfg3;
    }
    
    @Override
    public VoxelShape getShape(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final CollisionContext der) {
        return this.SHAPES_CACHE.get(((StateHolder<O, Object>)cfj).<Comparable, Integer>setValue((Property<Comparable>)RedStoneWireBlock.POWER, 0));
    }
    
    @Override
    public BlockState getStateForPlacement(final BlockPlaceContext bin) {
        return this.getConnectionState(bin.getLevel(), this.crossState, bin.getClickedPos());
    }
    
    private BlockState getConnectionState(final BlockGetter bpg, BlockState cfj, final BlockPos fu) {
        final boolean boolean5 = isDot(cfj);
        cfj = this.getMissingConnections(bpg, ((StateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Comparable>setValue((Property<Comparable>)RedStoneWireBlock.POWER, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.POWER)), fu);
        if (boolean5 && isDot(cfj)) {
            return cfj;
        }
        final boolean boolean6 = cfj.<RedstoneSide>getValue(RedStoneWireBlock.NORTH).isConnected();
        final boolean boolean7 = cfj.<RedstoneSide>getValue(RedStoneWireBlock.SOUTH).isConnected();
        final boolean boolean8 = cfj.<RedstoneSide>getValue(RedStoneWireBlock.EAST).isConnected();
        final boolean boolean9 = cfj.<RedstoneSide>getValue(RedStoneWireBlock.WEST).isConnected();
        final boolean boolean10 = !boolean6 && !boolean7;
        final boolean boolean11 = !boolean8 && !boolean9;
        if (!boolean9 && boolean10) {
            cfj = ((StateHolder<O, BlockState>)cfj).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.WEST, RedstoneSide.SIDE);
        }
        if (!boolean8 && boolean10) {
            cfj = ((StateHolder<O, BlockState>)cfj).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.EAST, RedstoneSide.SIDE);
        }
        if (!boolean6 && boolean11) {
            cfj = ((StateHolder<O, BlockState>)cfj).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.NORTH, RedstoneSide.SIDE);
        }
        if (!boolean7 && boolean11) {
            cfj = ((StateHolder<O, BlockState>)cfj).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.SOUTH, RedstoneSide.SIDE);
        }
        return cfj;
    }
    
    private BlockState getMissingConnections(final BlockGetter bpg, BlockState cfj, final BlockPos fu) {
        final boolean boolean5 = !bpg.getBlockState(fu.above()).isRedstoneConductor(bpg, fu);
        for (final Direction fz7 : Direction.Plane.HORIZONTAL) {
            if (!cfj.<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz7)).isConnected()) {
                final RedstoneSide cgn8 = this.getConnectingSide(bpg, fu, fz7, boolean5);
                cfj = ((StateHolder<O, BlockState>)cfj).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz7), cgn8);
            }
        }
        return cfj;
    }
    
    @Override
    public BlockState updateShape(final BlockState cfj1, final Direction fz, final BlockState cfj3, final LevelAccessor bqc, final BlockPos fu5, final BlockPos fu6) {
        if (fz == Direction.DOWN) {
            return cfj1;
        }
        if (fz == Direction.UP) {
            return this.getConnectionState(bqc, cfj1, fu5);
        }
        final RedstoneSide cgn8 = this.getConnectingSide(bqc, fu5, fz);
        if (cgn8.isConnected() == cfj1.<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz)).isConnected() && !isCross(cfj1)) {
            return ((StateHolder<O, BlockState>)cfj1).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz), cgn8);
        }
        return this.getConnectionState(bqc, (((StateHolder<O, BlockState>)this.crossState).setValue((Property<Comparable>)RedStoneWireBlock.POWER, (Comparable)cfj1.<V>getValue((Property<V>)RedStoneWireBlock.POWER))).<RedstoneSide, RedstoneSide>setValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz), cgn8), fu5);
    }
    
    private static boolean isCross(final BlockState cfj) {
        return cfj.<RedstoneSide>getValue(RedStoneWireBlock.NORTH).isConnected() && cfj.<RedstoneSide>getValue(RedStoneWireBlock.SOUTH).isConnected() && cfj.<RedstoneSide>getValue(RedStoneWireBlock.EAST).isConnected() && cfj.<RedstoneSide>getValue(RedStoneWireBlock.WEST).isConnected();
    }
    
    private static boolean isDot(final BlockState cfj) {
        return !cfj.<RedstoneSide>getValue(RedStoneWireBlock.NORTH).isConnected() && !cfj.<RedstoneSide>getValue(RedStoneWireBlock.SOUTH).isConnected() && !cfj.<RedstoneSide>getValue(RedStoneWireBlock.EAST).isConnected() && !cfj.<RedstoneSide>getValue(RedStoneWireBlock.WEST).isConnected();
    }
    
    @Override
    public void updateIndirectNeighbourShapes(final BlockState cfj, final LevelAccessor bqc, final BlockPos fu, final int integer4, final int integer5) {
        final BlockPos.MutableBlockPos a7 = new BlockPos.MutableBlockPos();
        for (final Direction fz9 : Direction.Plane.HORIZONTAL) {
            final RedstoneSide cgn10 = cfj.<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz9));
            if (cgn10 != RedstoneSide.NONE && !bqc.getBlockState(a7.setWithOffset(fu, fz9)).is(this)) {
                a7.move(Direction.DOWN);
                final BlockState cfj2 = bqc.getBlockState(a7);
                if (!cfj2.is(Blocks.OBSERVER)) {
                    final BlockPos fu2 = a7.relative(fz9.getOpposite());
                    final BlockState cfj3 = cfj2.updateShape(fz9.getOpposite(), bqc.getBlockState(fu2), bqc, a7, fu2);
                    Block.updateOrDestroy(cfj2, cfj3, bqc, a7, integer4, integer5);
                }
                a7.setWithOffset(fu, fz9).move(Direction.UP);
                final BlockState cfj4 = bqc.getBlockState(a7);
                if (cfj4.is(Blocks.OBSERVER)) {
                    continue;
                }
                final BlockPos fu3 = a7.relative(fz9.getOpposite());
                final BlockState cfj5 = cfj4.updateShape(fz9.getOpposite(), bqc.getBlockState(fu3), bqc, a7, fu3);
                Block.updateOrDestroy(cfj4, cfj5, bqc, a7, integer4, integer5);
            }
        }
    }
    
    private RedstoneSide getConnectingSide(final BlockGetter bpg, final BlockPos fu, final Direction fz) {
        return this.getConnectingSide(bpg, fu, fz, !bpg.getBlockState(fu.above()).isRedstoneConductor(bpg, fu));
    }
    
    private RedstoneSide getConnectingSide(final BlockGetter bpg, final BlockPos fu, final Direction fz, final boolean boolean4) {
        final BlockPos fu2 = fu.relative(fz);
        final BlockState cfj7 = bpg.getBlockState(fu2);
        if (boolean4) {
            final boolean boolean5 = this.canSurviveOn(bpg, fu2, cfj7);
            if (boolean5 && shouldConnectTo(bpg.getBlockState(fu2.above()))) {
                if (cfj7.isFaceSturdy(bpg, fu2, fz.getOpposite())) {
                    return RedstoneSide.UP;
                }
                return RedstoneSide.SIDE;
            }
        }
        if (shouldConnectTo(cfj7, fz) || (!cfj7.isRedstoneConductor(bpg, fu2) && shouldConnectTo(bpg.getBlockState(fu2.below())))) {
            return RedstoneSide.SIDE;
        }
        return RedstoneSide.NONE;
    }
    
    @Override
    public boolean canSurvive(final BlockState cfj, final LevelReader bqd, final BlockPos fu) {
        final BlockPos fu2 = fu.below();
        final BlockState cfj2 = bqd.getBlockState(fu2);
        return this.canSurviveOn(bqd, fu2, cfj2);
    }
    
    private boolean canSurviveOn(final BlockGetter bpg, final BlockPos fu, final BlockState cfj) {
        return cfj.isFaceSturdy(bpg, fu, Direction.UP) || cfj.is(Blocks.HOPPER);
    }
    
    private void updatePowerStrength(final Level bqb, final BlockPos fu, final BlockState cfj) {
        final int integer5 = this.calculateTargetStrength(bqb, fu);
        if (cfj.<Integer>getValue((Property<Integer>)RedStoneWireBlock.POWER) != integer5) {
            if (bqb.getBlockState(fu) == cfj) {
                bqb.setBlock(fu, ((StateHolder<O, BlockState>)cfj).<Comparable, Integer>setValue((Property<Comparable>)RedStoneWireBlock.POWER, integer5), 2);
            }
            final Set<BlockPos> set6 = Sets.newHashSet();
            set6.add(fu);
            for (final Direction fz10 : Direction.values()) {
                set6.add(fu.relative(fz10));
            }
            for (final BlockPos fu2 : set6) {
                bqb.updateNeighborsAt(fu2, this);
            }
        }
    }
    
    private int calculateTargetStrength(final Level bqb, final BlockPos fu) {
        this.shouldSignal = false;
        final int integer4 = bqb.getBestNeighborSignal(fu);
        this.shouldSignal = true;
        int integer5 = 0;
        if (integer4 < 15) {
            for (final Direction fz7 : Direction.Plane.HORIZONTAL) {
                final BlockPos fu2 = fu.relative(fz7);
                final BlockState cfj9 = bqb.getBlockState(fu2);
                integer5 = Math.max(integer5, this.getWireSignal(cfj9));
                final BlockPos fu3 = fu.above();
                if (cfj9.isRedstoneConductor(bqb, fu2) && !bqb.getBlockState(fu3).isRedstoneConductor(bqb, fu3)) {
                    integer5 = Math.max(integer5, this.getWireSignal(bqb.getBlockState(fu2.above())));
                }
                else {
                    if (cfj9.isRedstoneConductor(bqb, fu2)) {
                        continue;
                    }
                    integer5 = Math.max(integer5, this.getWireSignal(bqb.getBlockState(fu2.below())));
                }
            }
        }
        return Math.max(integer4, integer5 - 1);
    }
    
    private int getWireSignal(final BlockState cfj) {
        return cfj.is(this) ? cfj.<Integer>getValue((Property<Integer>)RedStoneWireBlock.POWER) : 0;
    }
    
    private void checkCornerChangeAt(final Level bqb, final BlockPos fu) {
        if (!bqb.getBlockState(fu).is(this)) {
            return;
        }
        bqb.updateNeighborsAt(fu, this);
        for (final Direction fz7 : Direction.values()) {
            bqb.updateNeighborsAt(fu.relative(fz7), this);
        }
    }
    
    @Override
    public void onPlace(final BlockState cfj1, final Level bqb, final BlockPos fu, final BlockState cfj4, final boolean boolean5) {
        if (cfj4.is(cfj1.getBlock()) || bqb.isClientSide) {
            return;
        }
        this.updatePowerStrength(bqb, fu, cfj1);
        for (final Direction fz8 : Direction.Plane.VERTICAL) {
            bqb.updateNeighborsAt(fu.relative(fz8), this);
        }
        this.updateNeighborsOfNeighboringWires(bqb, fu);
    }
    
    @Override
    public void onRemove(final BlockState cfj1, final Level bqb, final BlockPos fu, final BlockState cfj4, final boolean boolean5) {
        if (boolean5 || cfj1.is(cfj4.getBlock())) {
            return;
        }
        super.onRemove(cfj1, bqb, fu, cfj4, boolean5);
        if (bqb.isClientSide) {
            return;
        }
        for (final Direction fz10 : Direction.values()) {
            bqb.updateNeighborsAt(fu.relative(fz10), this);
        }
        this.updatePowerStrength(bqb, fu, cfj1);
        this.updateNeighborsOfNeighboringWires(bqb, fu);
    }
    
    private void updateNeighborsOfNeighboringWires(final Level bqb, final BlockPos fu) {
        for (final Direction fz5 : Direction.Plane.HORIZONTAL) {
            this.checkCornerChangeAt(bqb, fu.relative(fz5));
        }
        for (final Direction fz5 : Direction.Plane.HORIZONTAL) {
            final BlockPos fu2 = fu.relative(fz5);
            if (bqb.getBlockState(fu2).isRedstoneConductor(bqb, fu2)) {
                this.checkCornerChangeAt(bqb, fu2.above());
            }
            else {
                this.checkCornerChangeAt(bqb, fu2.below());
            }
        }
    }
    
    @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;
        }
        if (cfj.canSurvive(bqb, fu3)) {
            this.updatePowerStrength(bqb, fu3, cfj);
        }
        else {
            Block.dropResources(cfj, bqb, fu3);
            bqb.removeBlock(fu3, false);
        }
    }
    
    @Override
    public int getDirectSignal(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final Direction fz) {
        if (!this.shouldSignal) {
            return 0;
        }
        return cfj.getSignal(bpg, fu, fz);
    }
    
    @Override
    public int getSignal(final BlockState cfj, final BlockGetter bpg, final BlockPos fu, final Direction fz) {
        if (!this.shouldSignal || fz == Direction.DOWN) {
            return 0;
        }
        final int integer6 = cfj.<Integer>getValue((Property<Integer>)RedStoneWireBlock.POWER);
        if (integer6 == 0) {
            return 0;
        }
        if (fz == Direction.UP || this.getConnectionState(bpg, cfj, fu).<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz.getOpposite())).isConnected()) {
            return integer6;
        }
        return 0;
    }
    
    protected static boolean shouldConnectTo(final BlockState cfj) {
        return shouldConnectTo(cfj, null);
    }
    
    protected static boolean shouldConnectTo(final BlockState cfj, @Nullable final Direction fz) {
        if (cfj.is(Blocks.REDSTONE_WIRE)) {
            return true;
        }
        if (cfj.is(Blocks.REPEATER)) {
            final Direction fz2 = cfj.<Direction>getValue((Property<Direction>)RepeaterBlock.FACING);
            return fz2 == fz || fz2.getOpposite() == fz;
        }
        if (cfj.is(Blocks.OBSERVER)) {
            return fz == cfj.<Direction>getValue((Property<Direction>)ObserverBlock.FACING);
        }
        return cfj.isSignalSource() && fz != null;
    }
    
    @Override
    public boolean isSignalSource(final BlockState cfj) {
        return this.shouldSignal;
    }
    
    public static int getColorForPower(final int integer) {
        final Vector3f g2 = RedStoneWireBlock.COLORS[integer];
        return Mth.color(g2.x(), g2.y(), g2.z());
    }
    
    private void spawnParticlesAlongLine(final Level bqb, final Random random, final BlockPos fu, final Vector3f g, final Direction fz5, final Direction fz6, final float float7, final float float8) {
        final float float9 = float8 - float7;
        if (random.nextFloat() >= 0.2f * float9) {
            return;
        }
        final float float10 = 0.4375f;
        final float float11 = float7 + float9 * random.nextFloat();
        final double double13 = 0.5 + 0.4375f * fz5.getStepX() + float11 * fz6.getStepX();
        final double double14 = 0.5 + 0.4375f * fz5.getStepY() + float11 * fz6.getStepY();
        final double double15 = 0.5 + 0.4375f * fz5.getStepZ() + float11 * fz6.getStepZ();
        bqb.addParticle(new DustParticleOptions(g.x(), g.y(), g.z(), 1.0f), fu.getX() + double13, fu.getY() + double14, fu.getZ() + double15, 0.0, 0.0, 0.0);
    }
    
    @Override
    public void animateTick(final BlockState cfj, final Level bqb, final BlockPos fu, final Random random) {
        final int integer6 = cfj.<Integer>getValue((Property<Integer>)RedStoneWireBlock.POWER);
        if (integer6 == 0) {
            return;
        }
        for (final Direction fz8 : Direction.Plane.HORIZONTAL) {
            final RedstoneSide cgn9 = cfj.<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz8));
            switch (cgn9) {
                case UP: {
                    this.spawnParticlesAlongLine(bqb, random, fu, RedStoneWireBlock.COLORS[integer6], fz8, Direction.UP, -0.5f, 0.5f);
                }
                case SIDE: {
                    this.spawnParticlesAlongLine(bqb, random, fu, RedStoneWireBlock.COLORS[integer6], Direction.DOWN, fz8, 0.0f, 0.5f);
                    continue;
                }
                default: {
                    this.spawnParticlesAlongLine(bqb, random, fu, RedStoneWireBlock.COLORS[integer6], Direction.DOWN, fz8, 0.0f, 0.3f);
                    continue;
                }
            }
        }
    }
    
    @Override
    public BlockState rotate(final BlockState cfj, final Rotation cap) {
        switch (cap) {
            case CLOCKWISE_180: {
                return (((((StateHolder<O, BlockState>)cfj).setValue(RedStoneWireBlock.NORTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.EAST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.SOUTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.NORTH))).<RedstoneSide, Comparable>setValue(RedStoneWireBlock.WEST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.EAST));
            }
            case COUNTERCLOCKWISE_90: {
                return (((((StateHolder<O, BlockState>)cfj).setValue(RedStoneWireBlock.NORTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.EAST))).setValue(RedStoneWireBlock.EAST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.SOUTH))).setValue(RedStoneWireBlock.SOUTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.WEST))).<RedstoneSide, Comparable>setValue(RedStoneWireBlock.WEST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.NORTH));
            }
            case CLOCKWISE_90: {
                return (((((StateHolder<O, BlockState>)cfj).setValue(RedStoneWireBlock.NORTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.WEST))).setValue(RedStoneWireBlock.EAST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.NORTH))).setValue(RedStoneWireBlock.SOUTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.EAST))).<RedstoneSide, Comparable>setValue(RedStoneWireBlock.WEST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.SOUTH));
            }
            default: {
                return cfj;
            }
        }
    }
    
    @Override
    public BlockState mirror(final BlockState cfj, final Mirror bzj) {
        switch (bzj) {
            case LEFT_RIGHT: {
                return (((StateHolder<O, BlockState>)cfj).setValue(RedStoneWireBlock.NORTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.SOUTH))).<RedstoneSide, Comparable>setValue(RedStoneWireBlock.SOUTH, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.NORTH));
            }
            case FRONT_BACK: {
                return (((StateHolder<O, BlockState>)cfj).setValue(RedStoneWireBlock.EAST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.WEST))).<RedstoneSide, Comparable>setValue(RedStoneWireBlock.WEST, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.EAST));
            }
            default: {
                return super.mirror(cfj, bzj);
            }
        }
    }
    
    @Override
    protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> a) {
        a.add(RedStoneWireBlock.NORTH, RedStoneWireBlock.EAST, RedStoneWireBlock.SOUTH, RedStoneWireBlock.WEST, RedStoneWireBlock.POWER);
    }
    
    @Override
    public InteractionResult use(final BlockState cfj, final Level bqb, final BlockPos fu, final Player bec, final InteractionHand anf, final BlockHitResult deh) {
        if (!bec.abilities.mayBuild) {
            return InteractionResult.PASS;
        }
        if (isCross(cfj) || isDot(cfj)) {
            BlockState cfj2 = isCross(cfj) ? this.defaultBlockState() : this.crossState;
            cfj2 = ((StateHolder<O, BlockState>)cfj2).<Comparable, Comparable>setValue((Property<Comparable>)RedStoneWireBlock.POWER, (Comparable)cfj.<V>getValue((Property<V>)RedStoneWireBlock.POWER));
            cfj2 = this.getConnectionState(bqb, cfj2, fu);
            if (cfj2 != cfj) {
                bqb.setBlock(fu, cfj2, 3);
                this.updatesOnShapeChange(bqb, fu, cfj, cfj2);
                return InteractionResult.SUCCESS;
            }
        }
        return InteractionResult.PASS;
    }
    
    private void updatesOnShapeChange(final Level bqb, final BlockPos fu, final BlockState cfj3, final BlockState cfj4) {
        for (final Direction fz7 : Direction.Plane.HORIZONTAL) {
            final BlockPos fu2 = fu.relative(fz7);
            if (cfj3.<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz7)).isConnected() != cfj4.<RedstoneSide>getValue(RedStoneWireBlock.PROPERTY_BY_DIRECTION.get(fz7)).isConnected() && bqb.getBlockState(fu2).isRedstoneConductor(bqb, fu2)) {
                bqb.updateNeighborsAtExceptFromFacing(fu2, cfj4.getBlock(), fz7.getOpposite());
            }
        }
    }
    
    static {
        NORTH = BlockStateProperties.NORTH_REDSTONE;
        EAST = BlockStateProperties.EAST_REDSTONE;
        SOUTH = BlockStateProperties.SOUTH_REDSTONE;
        WEST = BlockStateProperties.WEST_REDSTONE;
        POWER = BlockStateProperties.POWER;
        PROPERTY_BY_DIRECTION = Maps.<Direction, Object>newEnumMap(ImmutableMap.<Direction, EnumProperty<RedstoneSide>>of(Direction.NORTH, RedStoneWireBlock.NORTH, Direction.EAST, RedStoneWireBlock.EAST, Direction.SOUTH, RedStoneWireBlock.SOUTH, Direction.WEST, RedStoneWireBlock.WEST));
        SHAPE_DOT = Block.box(3.0, 0.0, 3.0, 13.0, 1.0, 13.0);
        SHAPES_FLOOR = Maps.<Direction, Object>newEnumMap(ImmutableMap.<Direction, VoxelShape>of(Direction.NORTH, Block.box(3.0, 0.0, 0.0, 13.0, 1.0, 13.0), Direction.SOUTH, Block.box(3.0, 0.0, 3.0, 13.0, 1.0, 16.0), Direction.EAST, Block.box(3.0, 0.0, 3.0, 16.0, 1.0, 13.0), Direction.WEST, Block.box(0.0, 0.0, 3.0, 13.0, 1.0, 13.0)));
        SHAPES_UP = Maps.<Direction, Object>newEnumMap(ImmutableMap.<Direction, VoxelShape>of(Direction.NORTH, Shapes.or(RedStoneWireBlock.SHAPES_FLOOR.get(Direction.NORTH), Block.box(3.0, 0.0, 0.0, 13.0, 16.0, 1.0)), Direction.SOUTH, Shapes.or(RedStoneWireBlock.SHAPES_FLOOR.get(Direction.SOUTH), Block.box(3.0, 0.0, 15.0, 13.0, 16.0, 16.0)), Direction.EAST, Shapes.or(RedStoneWireBlock.SHAPES_FLOOR.get(Direction.EAST), Block.box(15.0, 0.0, 3.0, 16.0, 16.0, 13.0)), Direction.WEST, Shapes.or(RedStoneWireBlock.SHAPES_FLOOR.get(Direction.WEST), Block.box(0.0, 0.0, 3.0, 1.0, 16.0, 13.0))));
        COLORS = new Vector3f[16];
        for (int integer1 = 0; integer1 <= 15; ++integer1) {
            final float float2 = integer1 / 15.0f;
            final float float3 = float2 * 0.6f + ((float2 > 0.0f) ? 0.4f : 0.3f);
            final float float4 = Mth.clamp(float2 * float2 * 0.7f - 0.5f, 0.0f, 1.0f);
            final float float5 = Mth.clamp(float2 * float2 * 0.6f - 0.7f, 0.0f, 1.0f);
            RedStoneWireBlock.COLORS[integer1] = new Vector3f(float3, float4, float5);
        }
    }
}
