package net.minecraft.world.level.block;

import net.minecraft.world.level.block.state.AbstractStateHolder;
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 bjw, final BlockPos fk, final BlockState byj) {
        this.connections = Lists.newArrayList();
        this.level = bjw;
        this.pos = fk;
        this.state = byj;
        this.block = (BaseRailBlock)byj.getBlock();
        final RailShape bzn5 = byj.<RailShape>getValue(this.block.getShapeProperty());
        this.isStraight = this.block.isStraight();
        this.updateConnections(bzn5);
    }
    
    public List<BlockPos> getConnections() {
        return this.connections;
    }
    
    private void updateConnections(final RailShape bzn) {
        this.connections.clear();
        switch (bzn) {
            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 btl3 = this.getRail(this.connections.get(integer2));
            if (btl3 == null || !btl3.connectsTo(this)) {
                this.connections.remove(integer2--);
            }
            else {
                this.connections.set(integer2, btl3.pos);
            }
        }
    }
    
    private boolean hasRail(final BlockPos fk) {
        return BaseRailBlock.isRail(this.level, fk) || BaseRailBlock.isRail(this.level, fk.above()) || BaseRailBlock.isRail(this.level, fk.below());
    }
    
    @Nullable
    private RailState getRail(final BlockPos fk) {
        BlockPos fk2 = fk;
        BlockState byj4 = this.level.getBlockState(fk2);
        if (BaseRailBlock.isRail(byj4)) {
            return new RailState(this.level, fk2, byj4);
        }
        fk2 = fk.above();
        byj4 = this.level.getBlockState(fk2);
        if (BaseRailBlock.isRail(byj4)) {
            return new RailState(this.level, fk2, byj4);
        }
        fk2 = fk.below();
        byj4 = this.level.getBlockState(fk2);
        if (BaseRailBlock.isRail(byj4)) {
            return new RailState(this.level, fk2, byj4);
        }
        return null;
    }
    
    private boolean connectsTo(final RailState btl) {
        return this.hasConnection(btl.pos);
    }
    
    private boolean hasConnection(final BlockPos fk) {
        for (int integer3 = 0; integer3 < this.connections.size(); ++integer3) {
            final BlockPos fk2 = this.connections.get(integer3);
            if (fk2.getX() == fk.getX() && fk2.getZ() == fk.getZ()) {
                return true;
            }
        }
        return false;
    }
    
    protected int countPotentialConnections() {
        int integer2 = 0;
        for (final Direction fp4 : Direction.Plane.HORIZONTAL) {
            if (this.hasRail(this.pos.relative(fp4))) {
                ++integer2;
            }
        }
        return integer2;
    }
    
    private boolean canConnectTo(final RailState btl) {
        return this.connectsTo(btl) || this.connections.size() != 2;
    }
    
    private void connectTo(final RailState btl) {
        this.connections.add(btl.pos);
        final BlockPos fk3 = this.pos.north();
        final BlockPos fk4 = this.pos.south();
        final BlockPos fk5 = this.pos.west();
        final BlockPos fk6 = this.pos.east();
        final boolean boolean7 = this.hasConnection(fk3);
        final boolean boolean8 = this.hasConnection(fk4);
        final boolean boolean9 = this.hasConnection(fk5);
        final boolean boolean10 = this.hasConnection(fk6);
        RailShape bzn11 = null;
        if (boolean7 || boolean8) {
            bzn11 = RailShape.NORTH_SOUTH;
        }
        if (boolean9 || boolean10) {
            bzn11 = RailShape.EAST_WEST;
        }
        if (!this.isStraight) {
            if (boolean8 && boolean10 && !boolean7 && !boolean9) {
                bzn11 = RailShape.SOUTH_EAST;
            }
            if (boolean8 && boolean9 && !boolean7 && !boolean10) {
                bzn11 = RailShape.SOUTH_WEST;
            }
            if (boolean7 && boolean9 && !boolean8 && !boolean10) {
                bzn11 = RailShape.NORTH_WEST;
            }
            if (boolean7 && boolean10 && !boolean8 && !boolean9) {
                bzn11 = RailShape.NORTH_EAST;
            }
        }
        if (bzn11 == RailShape.NORTH_SOUTH) {
            if (BaseRailBlock.isRail(this.level, fk3.above())) {
                bzn11 = RailShape.ASCENDING_NORTH;
            }
            if (BaseRailBlock.isRail(this.level, fk4.above())) {
                bzn11 = RailShape.ASCENDING_SOUTH;
            }
        }
        if (bzn11 == RailShape.EAST_WEST) {
            if (BaseRailBlock.isRail(this.level, fk6.above())) {
                bzn11 = RailShape.ASCENDING_EAST;
            }
            if (BaseRailBlock.isRail(this.level, fk5.above())) {
                bzn11 = RailShape.ASCENDING_WEST;
            }
        }
        if (bzn11 == null) {
            bzn11 = RailShape.NORTH_SOUTH;
        }
        this.state = ((AbstractStateHolder<O, BlockState>)this.state).<RailShape, RailShape>setValue(this.block.getShapeProperty(), bzn11);
        this.level.setBlock(this.pos, this.state, 3);
    }
    
    private boolean hasNeighborRail(final BlockPos fk) {
        final RailState btl3 = this.getRail(fk);
        if (btl3 == null) {
            return false;
        }
        btl3.removeSoftConnections();
        return btl3.canConnectTo(this);
    }
    
    public RailState place(final boolean boolean1, final boolean boolean2, final RailShape bzn) {
        final BlockPos fk5 = this.pos.north();
        final BlockPos fk6 = this.pos.south();
        final BlockPos fk7 = this.pos.west();
        final BlockPos fk8 = this.pos.east();
        final boolean boolean3 = this.hasNeighborRail(fk5);
        final boolean boolean4 = this.hasNeighborRail(fk6);
        final boolean boolean5 = this.hasNeighborRail(fk7);
        final boolean boolean6 = this.hasNeighborRail(fk8);
        RailShape bzn2 = null;
        final boolean boolean7 = boolean3 || boolean4;
        final boolean boolean8 = boolean5 || boolean6;
        if (boolean7 && !boolean8) {
            bzn2 = RailShape.NORTH_SOUTH;
        }
        if (boolean8 && !boolean7) {
            bzn2 = 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) {
                bzn2 = RailShape.SOUTH_EAST;
            }
            if (boolean10 && !boolean3 && !boolean6) {
                bzn2 = RailShape.SOUTH_WEST;
            }
            if (boolean12 && !boolean4 && !boolean6) {
                bzn2 = RailShape.NORTH_WEST;
            }
            if (boolean11 && !boolean4 && !boolean5) {
                bzn2 = RailShape.NORTH_EAST;
            }
        }
        if (bzn2 == null) {
            if (boolean7 && boolean8) {
                bzn2 = bzn;
            }
            else if (boolean7) {
                bzn2 = RailShape.NORTH_SOUTH;
            }
            else if (boolean8) {
                bzn2 = RailShape.EAST_WEST;
            }
            if (!this.isStraight) {
                if (boolean1) {
                    if (boolean9) {
                        bzn2 = RailShape.SOUTH_EAST;
                    }
                    if (boolean10) {
                        bzn2 = RailShape.SOUTH_WEST;
                    }
                    if (boolean11) {
                        bzn2 = RailShape.NORTH_EAST;
                    }
                    if (boolean12) {
                        bzn2 = RailShape.NORTH_WEST;
                    }
                }
                else {
                    if (boolean12) {
                        bzn2 = RailShape.NORTH_WEST;
                    }
                    if (boolean11) {
                        bzn2 = RailShape.NORTH_EAST;
                    }
                    if (boolean10) {
                        bzn2 = RailShape.SOUTH_WEST;
                    }
                    if (boolean9) {
                        bzn2 = RailShape.SOUTH_EAST;
                    }
                }
            }
        }
        if (bzn2 == RailShape.NORTH_SOUTH) {
            if (BaseRailBlock.isRail(this.level, fk5.above())) {
                bzn2 = RailShape.ASCENDING_NORTH;
            }
            if (BaseRailBlock.isRail(this.level, fk6.above())) {
                bzn2 = RailShape.ASCENDING_SOUTH;
            }
        }
        if (bzn2 == RailShape.EAST_WEST) {
            if (BaseRailBlock.isRail(this.level, fk8.above())) {
                bzn2 = RailShape.ASCENDING_EAST;
            }
            if (BaseRailBlock.isRail(this.level, fk7.above())) {
                bzn2 = RailShape.ASCENDING_WEST;
            }
        }
        if (bzn2 == null) {
            bzn2 = bzn;
        }
        this.updateConnections(bzn2);
        this.state = ((AbstractStateHolder<O, BlockState>)this.state).<RailShape, RailShape>setValue(this.block.getShapeProperty(), bzn2);
        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 btl21 = this.getRail(this.connections.get(integer20));
                if (btl21 != null) {
                    btl21.removeSoftConnections();
                    if (btl21.canConnectTo(this)) {
                        btl21.connectTo(this);
                    }
                }
            }
        }
        return this;
    }
    
    public BlockState getState() {
        return this.state;
    }
}
