class Eth2PeerSelectionStrategy implements PeerSelectionStrategy {

  @Override
  public List<Peer> selectPeersToDisconnect(
      final P2PNetwork<?> network, final PeerPools peerPools) {

    final Map<PeerPool, List<Peer>> peersBySource =
        network
            .streamPeers()
            .collect(Collectors.groupingBy(peer -> peerPools.getPool(peer.getId())));

    final List<Peer> randomlySelectedPeers =
        peersBySource.getOrDefault(RANDOMLY_SELECTED, new ArrayList<>());
    final int randomlySelectedPeerCount = randomlySelectedPeers.size();

    final int currentPeerCount = network.getPeerCount();
    final int peersToDrop = targetPeerCountRange.getPeersToDrop(currentPeerCount);
    if (peersToDrop == 0) {
      return emptyList();
    }
    final PeerScorer peerScorer = peerSubnetSubscriptionsFactory.create(network).createScorer();
    final int randomlySelectedPeersToDrop =
        targetPeerCountRange.getRandomlySelectedPeersToDrop(
            randomlySelectedPeerCount, currentPeerCount);
    shuffler.shuffle(randomlySelectedPeers);
    final List<Peer> randomlySelectedPeersBeingDropped =
        randomlySelectedPeers.subList(
            0, Math.min(randomlySelectedPeersToDrop, randomlySelectedPeers.size()));
    // Peers from the randomly selected pool that have been chosen are moved have their special
    // randomly selected status revoked, leaving them in the default pool where they are considered
    // for disconnection based on their score
    randomlySelectedPeersBeingDropped.forEach(
        peer -> peerPools.addPeerToPool(peer.getId(), SCORE_BASED));
    return Stream.concat(
            randomlySelectedPeersBeingDropped.stream(),
            peersBySource.getOrDefault(SCORE_BASED, emptyList()).stream())
        .sorted(Comparator.comparing(peerScorer::scoreExistingPeer))
        .limit(peersToDrop)
        .collect(toList());
  }

  public  Eth2PeerSelectionStrategy(
      final TargetPeerRange targetPeerCountRange,
      final PeerSubnetSubscriptions.Factory peerSubnetSubscriptionsFactory,
      final ReputationManager reputationManager,
      final Shuffler shuffler);

}