class ImageHandler {

    public static Set<String> clusterImagesAndPickRepresentatives(Collection<String> imageUrls) {

        Set<String> selectedImages = new HashSet<>();

        // keep the index of the loaded image and tie it to the image URL
        Map<Integer, String> indexUrlMap = new HashMap<>();

        // load all images
        List<BufferedImage> loadedImages = new ArrayList<>();
        for (String imageUrl : imageUrls) {
            indexUrlMap.put(loadedImages.size(), imageUrl);
            BufferedImage loadedImage = load(imageUrl);
            loadedImages.add(loadedImage);
        }

        // hold the representatives per cluster, <clusterId,[imageIds]>
        Map<Integer, List<Integer>> representatives = new HashMap<>();

        // remember all image ids that are in a cluster already
        Set<Integer> clusteredImageIds = new HashSet<>();

        for (int i = 0; i < loadedImages.size(); i++) {

            BufferedImage image1 = loadedImages.get(i);

            boolean image1ClusteredAlready = !clusteredImageIds.add(i);
            if (!image1ClusteredAlready) {
                List<Integer> newList = new ArrayList<>();
                newList.add(i);
                representatives.put(i, newList);
            } else {
                continue;
            }

            // int image1PixelCount = getPixelCount(image1);

            for (int j = i + 1; j < loadedImages.size(); j++) {

                boolean image2ClusteredAlready = clusteredImageIds.contains(j);
                if (image2ClusteredAlready) {
                    continue;
                }

                BufferedImage image2 = loadedImages.get(j);
                boolean isDuplicate = isDuplicate(image1, image2);

                if (isDuplicate) {
                    representatives.get(i).add(j);
                    clusteredImageIds.add(j);
                }
            }
        }

        // pick highest resolving representative
        for (Entry<Integer, List<Integer>> cluster : representatives.entrySet()) {

            // System.out.println(cluster.getKey());
            // CollectionHelper.print(cluster.getValue());

            int highestPixelCount = 0;
            String highestResolutionImageUrl = "";
            for (Integer imageId : cluster.getValue()) {

                BufferedImage loadedImage = loadedImages.get(imageId);

                int pixelCount = getPixelCount(loadedImage);
                if (pixelCount > highestPixelCount) {
                    highestResolutionImageUrl = indexUrlMap.get(imageId);
                    highestPixelCount = pixelCount;
                }

            }

            selectedImages.add(highestResolutionImageUrl);

        }

        return selectedImages;
    }

}