package nl.rutgerkok.blocklocker.impl.blockfinder;

import java.util.ArrayList;
import java.util.List;

import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;

import nl.rutgerkok.blocklocker.SignParser;

final class ConnectedContainersBlockFinder extends BlockFinder {
    private static final int MAX_SEARCH_DISTANCE = 10;

    ConnectedContainersBlockFinder(SignParser parser) {
        super(parser);
    }

    @Override
    public List<Block> findContainerNeighbors(Block block) {
        Material containerMaterial = block.getType();
        List<Block> blocks = new ArrayList<>();
        blocks.add(block);

        // Search above and below on the starting block
        searchVertical(containerMaterial, block, blocks);

        // Just searches in the four cardinal faces, until it hits a block
        // of another type. Blocks above and below of the same block type are
        // also searched
        for (BlockFace face : CARDINAL_FACES) {
            int distance = 0;
            Block atPosition = block.getRelative(face);
            while (distance < MAX_SEARCH_DISTANCE && atPosition.getType() == containerMaterial) {
                blocks.add(atPosition);
                searchVertical(containerMaterial, atPosition, blocks);

                atPosition = atPosition.getRelative(face);
                distance++;
            }
        }

        BlockFace chestNeighborFace = this.getChestNeighborFaceOrNull(block);
        if (chestNeighborFace != null) {
            // Double chest, also perform search for other chest block
            Block chestNeighbor = block.getRelative(chestNeighborFace);
            BlockFace[] searchDirections = { this.turn90Degrees(chestNeighborFace),
                    this.turn90Degrees(chestNeighborFace).getOppositeFace() };
            for (BlockFace face : searchDirections) {
                int distance = 0;
                Block atPosition = chestNeighbor.getRelative(face);
                while (distance < MAX_SEARCH_DISTANCE && atPosition.getType() == containerMaterial) {
                    blocks.add(atPosition);
                    searchVertical(containerMaterial, atPosition, blocks);

                    atPosition = atPosition.getRelative(face);
                    distance++;
                }
            }
        }

        return blocks;
    }

    /**
     * Searches for blocks of the same type above and below the starting block.
     *
     * @param containerMaterial
     *            The material {@link Block#getType() startingBlock.getType()}
     *            returns.
     * @param startingBlock
     *            The starting block.
     * @param blocks
     *            All connected blocks above and below (so not the starting block
     *            itself) of the same type will be added to this list.
     */
    private void searchVertical(Material containerMaterial, Block startingBlock, List<Block> blocks) {
        for (BlockFace face : VERTICAL_FACES) {
            int distance = 0;
            Block atPosition = startingBlock.getRelative(face);
            while (distance < MAX_SEARCH_DISTANCE && atPosition.getType() == containerMaterial) {
                blocks.add(atPosition);

                atPosition = atPosition.getRelative(face);
                distance++;
            }
        }
    }

    /**
     * Adds a chest neighbor to the list of blocks, if any.
     *
     * @param addTo
     *            The list to add the block to.
     * @param searchingInFace
     *            The direction the search is going. As the search will reach blocks
     *            in this direction, and has already reached blocks in the oppisite
     *            direction, blocks in those two directions are not added to the
     *            block list.
     * @param block
     *            The block to search neighbors for.
     */
    private void tryAddChestNeighbor(List<Block> addTo, BlockFace searchingInFace, Block block) {
        if (searchingInFace == BlockFace.SELF) {
            // Not yet searching in any direction, so all four directions will be searched for in the future
            // So it is not useful to find neighbors already, as they will be found anyways
            return;
        }
        BlockFace connectedChestFace = this.getChestNeighborFaceOrNull(block);
        if (connectedChestFace != null
                && connectedChestFace != searchingInFace
                && connectedChestFace != searchingInFace.getOppositeFace()) {
            addTo.add(block.getRelative(connectedChestFace));
        }
    }
}

@@ -3354,1251 +3354,7 @@
    %7D
-%0A%0A    /**%0A     * Adds a chest neighbor to the list of blocks, if any.%0A     *%0A     * @param addTo%0A     *            The list to add the block to.%0A     * @param searchingInFace%0A     *            The direction the search is going. As the search will reach blocks%0A     *            in this direction, and has already reached blocks in the oppisite%0A     *            direction, blocks in those two directions are not added to the%0A     *            block list.%0A     * @param block%0A     *            The block to search neighbors for.%0A     */%0A    private void tryAddChestNeighbor(List%3CBlock%3E addTo, BlockFace searchingInFace, Block block) %7B%0A        if (searchingInFace == BlockFace.SELF) %7B%0A            // Not yet searching in any direction, so all four directions will be searched for in the future%0A            // So it is not useful to find neighbors already, as they will be found anyways%0A            return;%0A        %7D%0A        BlockFace connectedChestFace = this.getChestNeighborFaceOrNull(block);%0A        if (connectedChestFace != null%0A                && connectedChestFace != searchingInFace%0A                && connectedChestFace != searchingInFace.getOppositeFace()) %7B%0A            addTo.add(block.getRelative(connectedChestFace));%0A        %7D%0A    %7D
 %0A%7D%0A

Remove unused method