content: package ro.isdc.wro.maven.plugin.support;
  
  import static org.apache.commons.lang3.Validate.isTrue;
  
  import org.apache.maven.plugin.logging.Log;
  
  import ro.isdc.wro.model.resource.Resource;
  
  
  /**
   * Responsible for logging progress related details. Useful to find the best balance between "to much" vs "none"
   * details. This implementation will indicate the state of the progress after a given period of time (ex: each 5
   * seconds).
   *
   * @author Alex Objelean
   * @since 1.7.0
   * @created 27 May 2013
   */
  public class ProgressIndicator {
    private static final int DEFAULT_TIMEOUT_DELAY = 5000;
    /**
     * Counts total number of processed resources.
     */
    private int totalResources = 0;
    /**
     * Counts total number of resources with errors.
     */
    private int totalResourcesWithErrors = 0;
    /**
     * Counts total number of jshint errors.
     */
    private int totalFoundErrors = 0;
    /**
     * Number of milliseconds indicating how often an info log will be invoked.
     */
    private long timeoutDelay = DEFAULT_TIMEOUT_DELAY;
    private long lastInvocationTimestamp;
    private final Log log;
  
    public ProgressIndicator(final Log log) {
      this.log = log;
      updateLastInvocation();
    }
  
    private void updateLastInvocation() {
      lastInvocationTimestamp = System.currentTimeMillis();
    }
  
    /**
     * resets all counters to zero.
     */
    public void reset() {
      totalFoundErrors = 0;
      totalResources = 0;
      totalResourcesWithErrors = 0;
    }
  
    /**
     * Logs the summary as it was collected at this point.
     */
    public void logSummary() {
      final String message = totalFoundErrors == 0 ? "No lint errors found." : String.format(
          "Found %s errors in %s files.", totalFoundErrors, totalResourcesWithErrors);
      log.info("----------------------------------------");
      log.info(String.format("Total resources: %s", totalResources));
      log.info(message);
      log.info("----------------------------------------\n");
    }
  
    /**
     * A method which should be invoked on each new resource processing, having as a side effect an increment of the
     * counter holding the number of total processed resources.
     */
    public synchronized void onProcessingResource(final Resource resource) {
      totalResources++;
      log.debug("processing resource: " + resource.getUri());
      if (isLogRequired()) {
        log.info("Processed until now: " + getTotalResources() + ". Last processed: " + resource.getUri());
        updateLastInvocation();
      }
    }
  
    private boolean isLogRequired() {
      return System.currentTimeMillis() - lastInvocationTimestamp > timeoutDelay;
    }
  
    /**
     * This method has a side effect of incrementing the number of resources containing errors.
     *
     * @param errorsToAdd
     *          number of errors found during processing. This number will be added to the counter holding total number of
     *          found errors.
     */
    public void addFoundErrors(final int errorsToAdd) {
      isTrue(errorsToAdd > 0, "Cannot add negative number of errors");
      totalResourcesWithErrors++;
      totalFoundErrors += errorsToAdd;
    }
  
    /**
     * @return a total number of found errors.
     */
    public final int getTotalFoundErrors() {
      return totalFoundErrors;
    }
  
    /**
     * @VisibleForTesting
     */
    final int getTotalResources() {
      return totalResources;
    }
  
    /**
     * @VisibleForTesting
     */
    final int getTotalResourcesWithErrors() {
      return totalResourcesWithErrors;
    }
  
    /**
     * @param timeoutDelay
     *          Number of milliseconds to not log info to avoid verbose logging. Useful when running the plugin in large
     *          projects.
     */
    final void setTimeoutDelay(final long timeoutDelay) {
      this.timeoutDelay = timeoutDelay;
    }
  }
  