package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.StateHolder;
import java.util.Iterator;
import net.minecraft.core.Direction;
import javax.annotation.Nullable;
import net.minecraft.world.level.block.state.properties.RailShape;
import com.google.common.collect.Lists;
import java.util.List;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;

public class RailState {
    private final Level level;
    private final BlockPos pos;
    private final BaseRailBlock block;
    private BlockState state;
    private final boolean isStraight;
    private final List<BlockPos> connections;
    
    public RailState(final Level bqb, final BlockPos fu, final BlockState cfj) {
        this.connections = Lists.newArrayList();
        this.level = bqb;
        this.pos = fu;
        this.state = cfj;
        this.block = (BaseRailBlock)cfj.getBlock();
        final RailShape cgm5 = cfj.<RailShape>getValue(this.block.getShapeProperty());
        this.isStraight = this.block.isStraight();
        this.updateConnections(cgm5);
    }
    
    public List<BlockPos> getConnections() {
        return this.connections;
    }
    
    private void updateConnections(final RailShape cgm) {
        this.connections.clear();
        switch (cgm) {
            case NORTH_SOUTH: {
                this.connections.add(this.pos.north());
                this.connections.add(this.pos.south());
                break;
            }
            case EAST_WEST: {
                this.connections.add(this.pos.west());
                this.connections.add(this.pos.east());
                break;
            }
            case ASCENDING_EAST: {
                this.connections.add(this.pos.west());
                this.connections.add(this.pos.east().above());
                break;
            }
            case ASCENDING_WEST: {
                this.connections.add(this.pos.west().above());
                this.connections.add(this.pos.east());
                break;
            }
            case ASCENDING_NORTH: {
                this.connections.add(this.pos.north().above());
                this.connections.add(this.pos.south());
                break;
            }
            case ASCENDING_SOUTH: {
                this.connections.add(this.pos.north());
                this.connections.add(this.pos.south().above());
                break;
            }
            case SOUTH_EAST: {
                this.connections.add(this.pos.east());
                this.connections.add(this.pos.south());
                break;
            }
            case SOUTH_WEST: {
                this.connections.add(this.pos.west());
                this.connections.add(this.pos.south());
                break;
            }
            case NORTH_WEST: {
                this.connections.add(this.pos.west());
                this.connections.add(this.pos.north());
                break;
            }
            case NORTH_EAST: {
                this.connections.add(this.pos.east());
                this.connections.add(this.pos.north());
                break;
            }
        }
    }
    
    private void removeSoftConnections() {
        for (int integer2 = 0; integer2 < this.connections.size(); ++integer2) {
            final RailState cae3 = this.getRail(this.connections.get(integer2));
            if (cae3 == null || !cae3.connectsTo(this)) {
                this.connections.remove(integer2--);
            }
            else {
                this.connections.set(integer2, cae3.pos);
            }
        }
    }
    
    private boolean hasRail(final BlockPos fu) {
        return BaseRailBlock.isRail(this.level, fu) || BaseRailBlock.isRail(this.level, fu.above()) || BaseRailBlock.isRail(this.level, fu.below());
    }
    
    @Nullable
    private RailState getRail(final BlockPos fu) {
        BlockPos fu2 = fu;
        BlockState cfj4 = this.level.getBlockState(fu2);
        if (BaseRailBlock.isRail(cfj4)) {
            return new RailState(this.level, fu2, cfj4);
        }
        fu2 = fu.above();
        cfj4 = this.level.getBlockState(fu2);
        if (BaseRailBlock.isRail(cfj4)) {
            return new RailState(this.level, fu2, cfj4);
        }
        fu2 = fu.below();
        cfj4 = this.level.getBlockState(fu2);
        if (BaseRailBlock.isRail(cfj4)) {
            return new RailState(this.level, fu2, cfj4);
        }
        return null;
    }
    
    private boolean connectsTo(final RailState cae) {
        return this.hasConnection(cae.pos);
    }
    
    private boolean hasConnection(final BlockPos fu) {
        for (int integer3 = 0; integer3 < this.connections.size(); ++integer3) {
            final BlockPos fu2 = this.connections.get(integer3);
            if (fu2.getX() == fu.getX() && fu2.getZ() == fu.getZ()) {
                return true;
            }
        }
        return false;
    }
    
    protected int countPotentialConnections() {
        int integer2 = 0;
        for (final Direction fz4 : Direction.Plane.HORIZONTAL) {
            if (this.hasRail(this.pos.relative(fz4))) {
                ++integer2;
            }
        }
        return integer2;
    }
    
    private boolean canConnectTo(final RailState cae) {
        return this.connectsTo(cae) || this.connections.size() != 2;
    }
    
    private void connectTo(final RailState cae) {
        this.connections.add(cae.pos);
        final BlockPos fu3 = this.pos.north();
        final BlockPos fu4 = this.pos.south();
        final BlockPos fu5 = this.pos.west();
        final BlockPos fu6 = this.pos.east();
        final boolean boolean7 = this.hasConnection(fu3);
        final boolean boolean8 = this.hasConnection(fu4);
        final boolean boolean9 = this.hasConnection(fu5);
        final boolean boolean10 = this.hasConnection(fu6);
        RailShape cgm11 = null;
        if (boolean7 || boolean8) {
            cgm11 = RailShape.NORTH_SOUTH;
        }
        if (boolean9 || boolean10) {
            cgm11 = RailShape.EAST_WEST;
        }
        if (!this.isStraight) {
            if (boolean8 && boolean10 && !boolean7 && !boolean9) {
                cgm11 = RailShape.SOUTH_EAST;
            }
            if (boolean8 && boolean9 && !boolean7 && !boolean10) {
                cgm11 = RailShape.SOUTH_WEST;
            }
            if (boolean7 && boolean9 && !boolean8 && !boolean10) {
                cgm11 = RailShape.NORTH_WEST;
            }
            if (boolean7 && boolean10 && !boolean8 && !boolean9) {
                cgm11 = RailShape.NORTH_EAST;
            }
        }
        if (cgm11 == RailShape.NORTH_SOUTH) {
            if (BaseRailBlock.isRail(this.level, fu3.above())) {
                cgm11 = RailShape.ASCENDING_NORTH;
            }
            if (BaseRailBlock.isRail(this.level, fu4.above())) {
                cgm11 = RailShape.ASCENDING_SOUTH;
            }
        }
        if (cgm11 == RailShape.EAST_WEST) {
            if (BaseRailBlock.isRail(this.level, fu6.above())) {
                cgm11 = RailShape.ASCENDING_EAST;
            }
            if (BaseRailBlock.isRail(this.level, fu5.above())) {
                cgm11 = RailShape.ASCENDING_WEST;
            }
        }
        if (cgm11 == null) {
            cgm11 = RailShape.NORTH_SOUTH;
        }
        this.state = ((StateHolder<O, BlockState>)this.state).<RailShape, RailShape>setValue(this.block.getShapeProperty(), cgm11);
        this.level.setBlock(this.pos, this.state, 3);
    }
    
    private boolean hasNeighborRail(final BlockPos fu) {
        final RailState cae3 = this.getRail(fu);
        if (cae3 == null) {
            return false;
        }
        cae3.removeSoftConnections();
        return cae3.canConnectTo(this);
    }
    
    public RailState place(final boolean boolean1, final boolean boolean2, final RailShape cgm) {
        final BlockPos fu5 = this.pos.north();
        final BlockPos fu6 = this.pos.south();
        final BlockPos fu7 = this.pos.west();
        final BlockPos fu8 = this.pos.east();
        final boolean boolean3 = this.hasNeighborRail(fu5);
        final boolean boolean4 = this.hasNeighborRail(fu6);
        final boolean boolean5 = this.hasNeighborRail(fu7);
        final boolean boolean6 = this.hasNeighborRail(fu8);
        RailShape cgm2 = null;
        final boolean boolean7 = boolean3 || boolean4;
        final boolean boolean8 = boolean5 || boolean6;
        if (boolean7 && !boolean8) {
            cgm2 = RailShape.NORTH_SOUTH;
        }
        if (boolean8 && !boolean7) {
            cgm2 = RailShape.EAST_WEST;
        }
        final boolean boolean9 = boolean4 && boolean6;
        final boolean boolean10 = boolean4 && boolean5;
        final boolean boolean11 = boolean3 && boolean6;
        final boolean boolean12 = boolean3 && boolean5;
        if (!this.isStraight) {
            if (boolean9 && !boolean3 && !boolean5) {
                cgm2 = RailShape.SOUTH_EAST;
            }
            if (boolean10 && !boolean3 && !boolean6) {
                cgm2 = RailShape.SOUTH_WEST;
            }
            if (boolean12 && !boolean4 && !boolean6) {
                cgm2 = RailShape.NORTH_WEST;
            }
            if (boolean11 && !boolean4 && !boolean5) {
                cgm2 = RailShape.NORTH_EAST;
            }
        }
        if (cgm2 == null) {
            if (boolean7 && boolean8) {
                cgm2 = cgm;
            }
            else if (boolean7) {
                cgm2 = RailShape.NORTH_SOUTH;
            }
            else if (boolean8) {
                cgm2 = RailShape.EAST_WEST;
            }
            if (!this.isStraight) {
                if (boolean1) {
                    if (boolean9) {
                        cgm2 = RailShape.SOUTH_EAST;
                    }
                    if (boolean10) {
                        cgm2 = RailShape.SOUTH_WEST;
                    }
                    if (boolean11) {
                        cgm2 = RailShape.NORTH_EAST;
                    }
                    if (boolean12) {
                        cgm2 = RailShape.NORTH_WEST;
                    }
                }
                else {
                    if (boolean12) {
                        cgm2 = RailShape.NORTH_WEST;
                    }
                    if (boolean11) {
                        cgm2 = RailShape.NORTH_EAST;
                    }
                    if (boolean10) {
                        cgm2 = RailShape.SOUTH_WEST;
                    }
                    if (boolean9) {
                        cgm2 = RailShape.SOUTH_EAST;
                    }
                }
            }
        }
        if (cgm2 == RailShape.NORTH_SOUTH) {
            if (BaseRailBlock.isRail(this.level, fu5.above())) {
                cgm2 = RailShape.ASCENDING_NORTH;
            }
            if (BaseRailBlock.isRail(this.level, fu6.above())) {
                cgm2 = RailShape.ASCENDING_SOUTH;
            }
        }
        if (cgm2 == RailShape.EAST_WEST) {
            if (BaseRailBlock.isRail(this.level, fu8.above())) {
                cgm2 = RailShape.ASCENDING_EAST;
            }
            if (BaseRailBlock.isRail(this.level, fu7.above())) {
                cgm2 = RailShape.ASCENDING_WEST;
            }
        }
        if (cgm2 == null) {
            cgm2 = cgm;
        }
        this.updateConnections(cgm2);
        this.state = ((StateHolder<O, BlockState>)this.state).<RailShape, RailShape>setValue(this.block.getShapeProperty(), cgm2);
        if (boolean2 || this.level.getBlockState(this.pos) != this.state) {
            this.level.setBlock(this.pos, this.state, 3);
            for (int integer20 = 0; integer20 < this.connections.size(); ++integer20) {
                final RailState cae21 = this.getRail(this.connections.get(integer20));
                if (cae21 != null) {
                    cae21.removeSoftConnections();
                    if (cae21.canConnectTo(this)) {
                        cae21.connectTo(this);
                    }
                }
            }
        }
        return this;
    }
    
    public BlockState getState() {
        return this.state;
    }
}
