/**
 * Copyright wro4j@2011
 */
package ro.isdc.wro.maven.plugin;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;

import ro.isdc.wro.WroRuntimeException;
import ro.isdc.wro.extensions.processor.js.JsHintProcessor;
import ro.isdc.wro.extensions.processor.support.linter.LinterError;
import ro.isdc.wro.extensions.processor.support.linter.LinterException;
import ro.isdc.wro.extensions.support.lint.LintReport;
import ro.isdc.wro.extensions.support.lint.ReportXmlFormatter;
import ro.isdc.wro.extensions.support.lint.ReportXmlFormatter.FormatterType;
import ro.isdc.wro.extensions.support.lint.ResourceLintReport;
import ro.isdc.wro.model.resource.Resource;
import ro.isdc.wro.model.resource.processor.ResourcePreProcessor;


/**
 * Maven plugin used to validate js scripts defined in wro model using <a href="http://jshint.com/">jsLint</a>.
 *
 * @goal jshint
 * @phase compile
 * @requiresDependencyResolution runtime
 * @author Alex Objelean
 * @since 1.3.5
 */
public class JsHintMojo
    extends AbstractLinterMojo<LinterError> {
  /**
   * File where the report will be written.
   *
   * @parameter default-value="${project.build.directory}/wro4j-reports/jshint.xml" expression="${reportFile}"
   * @optional
   */
  private File reportFile;
  /**
   * The preferred format of the report.
   *
   * @parameter expression="${reportFormat}"
   * @optional
   */
  private String reportFormat = FormatterType.JSLINT.getFormat();

  private int processedResources = 0;
  private int foundErrors = 0;

  /**
   * {@inheritDoc}
   */
  @Override
  protected ResourcePreProcessor createResourceProcessor() {
    final ResourcePreProcessor processor = new JsHintProcessor() {
      @Override
      public void process(final Resource resource, final Reader reader, final Writer writer)
          throws IOException {
        processedResources++;
        getLog().info("processing resource: " + resource);
        // use StringWriter to discard the merged processed result (linting is useful only for reporting errors).
        super.process(resource, reader, new StringWriter());
      }

      @Override
      protected void onException(final WroRuntimeException e) {
        JsHintMojo.this.onException(e);
      }

      @Override
      protected void onLinterException(final LinterException e, final Resource resource) {
        final String errorMessage = String.format("%s errors found while processing resource: %s. Errors are: %s", e
            .getErrors().size(), resource, e.getErrors());
        foundErrors += e.getErrors().size();
        getLog().error(errorMessage);
        // collect found errors
        addReport(ResourceLintReport.create(resource.getUri(), e.getErrors()));
        if (!isFailNever()) {
          throw new WroRuntimeException("Errors found when validating resource: " + resource);
        }
      };
    }.setOptionsAsString(getOptions());
    return processor;
  }

  @Override
  protected void onAfterExecute() {
    getLog().info("ONAFTEREXECUTE");
    getLog().info(String.format("JSHINT found %s errors in %s files", foundErrors, processedResources));
    super.onAfterExecute();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected ReportXmlFormatter createXmlFormatter(final LintReport<LinterError> lintReport, final FormatterType type) {
    return ReportXmlFormatter.createForLinterError(lintReport, type);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected File getReportFile() {
    return reportFile;
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected String getReportFormat() {
    return reportFormat;
  }

  /**
   * @VisibleForTesting
   */
  void setReportFile(final File reportFile) {
    this.reportFile = reportFile;
  }

  /**
   * @param reportFormat
   *          the preferred report format.
   * @VisibleForTesting
   */
  void setReportFormat(final String reportFormat) {
    this.reportFormat = reportFormat;
  }

  /**
   * Used by unit test to check if mojo doesn't fail.
   *
   * @VisibleForTesting
   */
  @Override
  void onException(final Exception e) {
  }
}

@@ -1566,25 +1566,21 @@
 ate int 
-processed
+total
 Resource
@@ -1601,17 +1601,22 @@
 ate int 
-f
+totalF
 oundErro
@@ -1954,25 +1954,21 @@
         
-processed
+total
 Resource
@@ -2650,17 +2650,22 @@
         
-f
+totalF
 oundErro
@@ -3065,16 +3065,224 @@
 %0A  %7D%0D%0A%0D%0A
+  /**%0D%0A   * %7B@inheritDoc%7D%0D%0A   */%0D%0A  @Override%0D%0A  protected void onBeforeExecute() %7B%0D%0A    totalFoundErrors = 0;%0D%0A    totalResources = 0;%0D%0A    super.onBeforeExecute();%0D%0A  %7D%0D%0A%0D%0A  /**%0D%0A   * %7B@inheritDoc%7D%0D%0A   */%0D%0A
   @Overr
@@ -3346,22 +3346,50 @@
 fo(%22
-ONAFTEREXECUTE
+%5Cn----------------------------------------
 %22);%0D
@@ -3459,17 +3459,22 @@
 files%22, 
-f
+totalF
 oundErro
@@ -3477,25 +3477,21 @@
 Errors, 
-processed
+total
 Resource
@@ -3492,24 +3492,90 @@
 sources));%0D%0A
+    getLog().info(%22----------------------------------------%5Cn%22);%0D%0A
     super.on

improve log formatting