package com.github.ferstl.jarscan;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.adoptopenjdk.jitwatch.jarscan.JarScan;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.ScopeArtifactFilter;
import org.apache.maven.shared.artifact.filter.StrictPatternExcludesArtifactFilter;
import org.apache.maven.shared.artifact.filter.StrictPatternIncludesArtifactFilter;

@Mojo(
    name = "scan",
    aggregator = false,
    defaultPhase = LifecyclePhase.NONE,
    inheritByDefault = false,
    requiresDependencyCollection = ResolutionScope.TEST,
    requiresDependencyResolution = ResolutionScope.TEST,
    requiresDirectInvocation = false,
    threadSafe = true)
public class JarScanMojo extends AbstractMojo {

  @Component
  private MavenProject project;

  /**
   * The scope of the artifacts that should be included.
   *
   * @since 1.0.0
   */
  @Parameter(property = "scope")
  private String scope;

  /**
   * Comma-separated list of artifacts to be included in the form of {@code groupId:artifactId:type:classifier}.
   *
   * @since 1.0.0
   */
  @Parameter(property = "includes", defaultValue = "")
  private List<String> includes;

  /**
   * Comma-separated list of artifacts to be excluded in the form of {@code groupId:artifactId:type:classifier}.
   *
   * @since 1.0.0
   */
  @Parameter(property = "excludes", defaultValue = "")
  private List<String> excludes;

  @Override
  public void execute() throws MojoExecutionException, MojoFailureException {
    @SuppressWarnings("unchecked")
    Set<Artifact> dependencies = this.project.getDependencyArtifacts();

    ArtifactFilter filter = createArtifactFilter();

    for (Artifact dependency : dependencies) {
      if (filter.include(dependency)) {
        try {
          System.out.println("Scanning " + dependency);
          JarScan.iterateJar(dependency.getFile(), 325, new PrintWriter(new OutputStreamWriter(System.out)));
          System.out.println("done: " + dependency);
          System.out.println();
        } catch (IOException e) {
          throw new MojoExecutionException(e.getMessage());
        }
      }
    }
  }

  private ArtifactFilter createArtifactFilter() {
    List<ArtifactFilter> filters = new ArrayList<>(3);

    if (this.scope != null) {
      filters.add(new ScopeArtifactFilter(this.scope));
    }

    if (!this.includes.isEmpty()) {
      filters.add(new StrictPatternIncludesArtifactFilter(this.includes));
    }

    if (!this.excludes.isEmpty()) {
      filters.add(new StrictPatternExcludesArtifactFilter(this.excludes));
    }

    return new AndArtifactFilter(filters);
  }

}

@@ -29,16 +29,37 @@
 rscan;%0A%0A
+import java.io.File;%0A
 import j
@@ -133,32 +133,60 @@
 io.PrintWriter;%0A
+import java.nio.file.Files;%0A
 import java.util
@@ -1186,16 +1186,138 @@
 ilter;%0A%0A
+import static java.nio.file.StandardOpenOption.CREATE;%0Aimport static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;%0A%0A
 @Mojo(%0A 
@@ -2322,16 +2322,200 @@
 ludes;%0A%0A
+  /**%0A   * The path of the report file. If not set the report is written to the console.%0A   *%0A   * @since 1.0.0%0A   */%0A  @Parameter(property = %22reportFile%22)%0A  private File reportFile;%0A%0A
   @Overr
@@ -2856,16 +2856,59 @@
     try 
+(PrintWriter writer = createReportWriter())
 %7B%0A      
@@ -3017,59 +3017,14 @@
 25, 
-new PrintWriter(new OutputStreamWriter(System.out))
+writer
 );%0A 
@@ -3230,16 +3230,362 @@
  %7D%0A  %7D%0A%0A
+  private PrintWriter createReportWriter() throws IOException%7B%0A    if (this.reportFile != null) %7B%0A      return new PrintWriter(Files.newBufferedWriter(this.reportFile.toPath(), CREATE, TRUNCATE_EXISTING));%0A    %7D%0A%0A    return new PrintWriter(new OutputStreamWriter(System.out)) %7B%0A      @Override%0A      public void close() %7B /* NOP */ %7D%0A    %7D;%0A  %7D%0A%0A
   privat

Add option for report file