class CheckpointHeaderFetcher {

  public CompletableFuture<List<BlockHeader>> getNextCheckpointHeaders(
      final EthPeer peer, final BlockHeader previousCheckpointHeader) {
    final int skip = syncConfig.getDownloaderChainSegmentSize() - 1;
    final int maximumHeaderRequestSize = syncConfig.getDownloaderHeaderRequestSize();
    final long previousCheckpointNumber = previousCheckpointHeader.getNumber();

    final int additionalHeaderCount;
    if (finalCheckpointHeader.isPresent()) {
      final BlockHeader targetHeader = finalCheckpointHeader.get();
      final long blocksUntilTarget = targetHeader.getNumber() - previousCheckpointNumber;
      if (blocksUntilTarget <= 0) {
        return completedFuture(emptyList());
      }
      final long maxHeadersToRequest = blocksUntilTarget / (skip + 1);
      additionalHeaderCount = (int) Math.min(maxHeadersToRequest, maximumHeaderRequestSize);
      if (additionalHeaderCount == 0) {
        return completedFuture(singletonList(targetHeader));
      }
    } else {
      additionalHeaderCount = maximumHeaderRequestSize;
    }

    return requestHeaders(peer, previousCheckpointHeader, additionalHeaderCount, skip);
  }

  public  CheckpointHeaderFetcher(
      final SynchronizerConfiguration syncConfig,
      final ProtocolSchedule protocolSchedule,
      final EthContext ethContext,
      final Optional<BlockHeader> finalCheckpointHeader,
      final MetricsSystem metricsSystem);

}