class RoundRobinAgendaScheduler implements AgendaScheduler {

    @Override
    public List<ReadyAgenda> schedule(final int requestCount, Insight insight, InsightScheduleInfo insightScheduleInfo)
    {
        if(requestCount == 0) return null;

        PendingCustomersDecorator pendingCustomersDecorator = getPendingCustomerIds(insightScheduleInfo, insight);
        List<String> pendingCustomerIds = pendingCustomersDecorator.getPendingCustomerIds();
        if(pendingCustomerIds == null || pendingCustomerIds.size() == 0)
        {
            logger.info("No pending customers for insightId: {} Exiting.", insight.getId());
            return null;
        }

        // These are kept separate because a customer in pass one should not be removed from the pool for future queue
        List<ReadyAgenda> passOneScheduledReadyAgendas = new LinkedList<>();

        Map<String, List<ReadyAgenda>> customerReadyAgendaMap = new HashMap<>();
        List<ReadyAgenda> passTwoScheduledReadyAgendas = new LinkedList<>();

        // PASS 1: perform round robin with the remaining customer ids
        performSchedulingPass(pendingCustomerIds, insight, passOneScheduledReadyAgendas, customerReadyAgendaMap, requestCount);
        if(passOneScheduledReadyAgendas.size() >= requestCount)
        {
            // remove any customer that had work scheduled
            pendingCustomerIds.removeAll(
                passOneScheduledReadyAgendas.stream().map(ReadyAgenda::getCustomerId).collect(Collectors.toList())
            );
        }
        else
        {
            final int passTwoRequestCount = requestCount - passOneScheduledReadyAgendas.size();
            // PASS 2: Use all customers to perform round robin (new pool)
            List<String> allCustomerIds = pendingCustomersDecorator.isFullSet()
                                          ? pendingCustomersDecorator.getPendingCustomerIds()
                                          : getAllCustomersForResourcePool(insight.getResourcePoolId());

            // loop through all the customers until the request count is met or no items remain
            while(true)
            {
                int beforeRoundSize = passTwoScheduledReadyAgendas.size();
                performSchedulingPass(allCustomerIds, insight, passTwoScheduledReadyAgendas, customerReadyAgendaMap, passTwoRequestCount);
                // repeating the process did not yield any more items OR requested count was met
                if(passTwoScheduledReadyAgendas.size() >= passTwoRequestCount ||
                    beforeRoundSize == passTwoScheduledReadyAgendas.size()) break;
            }

            // remove any customers scheduled from the second pass from the entire pool
            pendingCustomerIds = allCustomerIds;
            pendingCustomerIds.removeAll(
                passTwoScheduledReadyAgendas.stream().map(ReadyAgenda::getCustomerId).collect(Collectors.toList())
            );
        }

        List<ReadyAgenda> scheduledReadyAgendas = Stream.concat(passOneScheduledReadyAgendas.stream(), passTwoScheduledReadyAgendas.stream())
            .collect(Collectors.toList());

        // set the new pending list
        insightScheduleInfo.setPendingCustomerIds(pendingCustomerIds);

        logger.info("RoundRobin Result -- InsightId: {} Scheduled: {} Requested: {} PendingCustomerIds: {}",
            insight.getId(),
            scheduledReadyAgendas.size(),
            requestCount,
            insightScheduleInfo.getPendingCustomerIds() == null ? null : insightScheduleInfo.getPendingCustomerIds().size());

        return scheduledReadyAgendas;
    }

    public  RoundRobinAgendaScheduler(ObjectPersister<ReadyAgenda> readyAgendaPersister, ObjectClient<Customer> customerClient);

}