package ru.samsu.mj.collection;

import ru.samsu.mj.board.Board;
import ru.samsu.mj.board.PartialComparison;

import java.util.*;

public class SortedBoardCollection {
    private final Map<Board, BoardCollection> MAP;
    private final Board THE_LEAST_BOARD;

    private SortedBoardCollection(Map<Board, BoardCollection> map, Board theLeastBoard) {
        MAP = map;
        THE_LEAST_BOARD = theLeastBoard;
    }

    static SortedBoardCollection valueOf(Collection<Board> boardCollection) {
        Map<Board, BoardCollection> map = new HashMap<>();
        Board theLeastBoard = null;
        Set<Board> buffer = new HashSet<>();

        // Initialization.
        for (Board board : boardCollection)
            if (board.isEmpty())
                theLeastBoard = board;
            else
                buffer.add(board);

        // Sorting itself.
        Set<Board> lastLayer = Collections.singleton(theLeastBoard);
        while (!buffer.isEmpty()) {
            Set<Board> nextLayer = nextLayer(buffer);
            injectMapping(map, lastLayer, nextLayer);
            buffer.removeAll(nextLayer);
            lastLayer = nextLayer;
        }

        return new SortedBoardCollection(map, theLeastBoard);
    }

    private static void injectMapping(Map<Board, BoardCollection> map, Set<Board> lastLayer, Set<Board> nextLayer) {
        for (Board oneBoard : lastLayer) {
            Set<Board> imageSet = new HashSet<>();// and `oneBoard` is its key
            for (Board anotherBoard : nextLayer)
                if (oneBoard.partiallyCompare(anotherBoard) == PartialComparison.LESS)
                    imageSet.add(anotherBoard);
            map.put(oneBoard, BoardCollection.valueOf(imageSet));
        }
    }

    /**
     * @param buffer --- the set of `Board`s to choose from.
     * @return the subset of `Board`s that are no greater than any other one in `buffer`.
     */
    private static Set<Board> nextLayer(Set<Board> buffer) {
        Set<Board> result = new HashSet<>();
        for (Board oneBoard : buffer) {
            boolean isGreaterThanSome = false;
            for (Board anotherBoard : buffer) {
                if (oneBoard.partiallyCompare(anotherBoard) == PartialComparison.GREATER) {
                    isGreaterThanSome = true;
                    break;
                }
            }
            if (isGreaterThanSome)
                continue;
            result.add(oneBoard);
        }
        return result;
    }

    public Board theLeast() {
        return THE_LEAST_BOARD;
    }

    public BoardCollection closestAbove(Board board) {
        return MAP.get(board);
    }
}

@@ -159,16 +159,43 @@
 lection 
+extends AbstractCollection 
 %7B%0A    pr
@@ -2655,11 +2655,220 @@
 );%0A    %7D
+%0A%0A    @Override%0A    public Iterator iterator() %7B%0A        throw new UnsupportedOperationException(%22will be implemented eventually%22);%0A    %7D%0A%0A    @Override%0A    public int size() %7B%0A        return MAP.size();%0A    %7D
 %0A%7D%0A

Extend AbstractCollection from SortedBoardCollection.