docs: @Override
      public CallEvent next(long systemCurrentTimeMillis) {
          // check for time passing
          if (systemCurrentTimeMillis > currentSystemMilliTimestamp) {
              // build a target for this 1ms window
              long eventBacklog = targetEventsThisMillisecond - eventsSoFarThisMillisecond;
              targetEventsThisMillisecond = (long) Math.floor(targetEventsPerMillisecond);
              double targetFraction = targetEventsPerMillisecond - targetEventsThisMillisecond;
              targetEventsThisMillisecond += (rand.nextDouble() <= targetFraction) ? 1 : 0;
              targetEventsThisMillisecond += eventBacklog;
              // reset counter for this 1ms window
              eventsSoFarThisMillisecond = 0;
              currentSystemMilliTimestamp = systemCurrentTimeMillis;
          }
  
          // drain scheduled events first
          CallEvent callEvent = delayedEvents.nextReady(systemCurrentTimeMillis);
          if (callEvent != null) {
              // double check this is an end event
              assert(callEvent.startTS == null);
              assert(callEvent.endTS != null);
  
              // return the agent/phone for this event to the available lists
              agentsAvailable.add(callEvent.agentId);
              phoneNumbersAvailable.add(callEvent.phoneNo);
  
              validate();
              return callEvent;
          }
  
          // check if we made all the target events for this 1ms window
          if (targetEventsThisMillisecond == eventsSoFarThisMillisecond) {
              validate();
              return null;
          }
  
          // generate rando event (begin/end pair)
          CallEvent[] event = makeRandomEvent();
          // this means all agents are busy
          if (event == null) {
              validate();
              return null;
          }
  
          // schedule the end event
          long endTimeKey = event[1].endTS.getTime();
          assert((endTimeKey - systemCurrentTimeMillis) < (config.maxcalldurationseconds * 1000));
          delayedEvents.add(endTimeKey, event[1]);
  
          eventsSoFarThisMillisecond++;
  
          validate();
          return event[0];
      }