/*
 * FindBugs - Find Bugs in Java programs
 * Copyright (C) 2003-2008 University of Maryland
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package edu.umd.cs.findbugs.workflow;

import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Date;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.dom4j.DocumentException;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugRankCategory;
import edu.umd.cs.findbugs.FindBugs;
import edu.umd.cs.findbugs.ProjectStats;
import edu.umd.cs.findbugs.SortedBugCollection;
import edu.umd.cs.findbugs.cloud.Cloud;
import edu.umd.cs.findbugs.config.CommandLine;

/**
 * @author bill.pugh
 */
public class CloudSyncAndReport {
	
	public static class CSPoptions {

		public String analysisFile;
		
		public String cloudSummary;

		public String cloudId;
		
		public int ageInHours = 22;
	}
	
	static class CSRCommandLine extends CommandLine {

		final CSPoptions options;

		public CSRCommandLine(CSPoptions options) {
			this.options = options;
			addOption("-cloud", "id", "id of the cloud to use");
			addOption("-recent", "hours", "maximum age in hours for an issue to be recent");
			addOption("-cloudSummary", "file", "write a cloud summary to thie file");
				}

		/* (non-Javadoc)
         * @see edu.umd.cs.findbugs.config.CommandLine#handleOption(java.lang.String, java.lang.String)
         */
        @Override
        protected void handleOption(String option, String optionExtraPart) throws IOException {
        	throw new IllegalArgumentException("Unknown option : " + option);

	        
        }

		/* (non-Javadoc)
         * @see edu.umd.cs.findbugs.config.CommandLine#handleOptionWithArgument(java.lang.String, java.lang.String)
         */
        @Override
        protected void handleOptionWithArgument(String option, String argument) throws IOException {
	      if (option.equals("-cloud")) {
	    	  options.cloudId = argument;
	      } else if (option.equals("-recent")) {
	    	  options.ageInHours = Integer.parseInt(argument);  
	      }else if (option.equals("-cloudSummary")) {
	    	  options.cloudSummary = argument; 
	      } else
	    	  throw new IllegalArgumentException("Unknown option : " + option);
        }
	}
	

	public static void main(String[] argv) throws Exception {

		FindBugs.setNoAnalysis();
		final CSPoptions options = new CSPoptions();
		final CSRCommandLine commandLine = new CSRCommandLine(options);
		int argCount = commandLine.parse(argv, 0, 1, "Usage: " + CloudSyncAndReport.class.getName()
		        + " [options] [<results1> <results2> ... <resultsn>] ");

		if (argCount < argv.length)
			options.analysisFile = argv[argCount];
		
		CloudSyncAndReport csr = new CloudSyncAndReport(options);
		csr.load();
		
		csr.sync();
		PrintWriter out = new PrintWriter(System.out);
		csr.report(out);
		out.flush();
		csr.shutdown();
		out.close();
	}
	
	final CSPoptions options;
	final SortedBugCollection bugCollection = new SortedBugCollection();
	
	/**
     * @param options
     */
    public CloudSyncAndReport(CSPoptions options) {
	   this.options = options;
	   
	   
    }
    public void load() throws IOException, DocumentException {
    	if (options.analysisFile == null)
    		bugCollection.readXML(new InputStreamReader(System.in));
    	else
    		bugCollection.readXML(options.analysisFile);
    	if (options.cloudId != null && !options.cloudId.equals(bugCollection.getProject().getCloudId())) {
    		bugCollection.getProject().setCloudId(options.cloudId);
    		bugCollection.reinitializeCloud();
    		}
    }
    
    public void sync()  {
    	Cloud cloud = bugCollection.getCloud();
    	cloud.initiateCommunication();
    	cloud.waitUntilIssueDataDownloaded();
    }
    
    static class Stats {
    	int total, recent;
    	
    }
    public void report(PrintWriter out)  {
    	TreeMap<BugRankCategory, Stats> stats =  new TreeMap<BugRankCategory,Stats>();
    	ProjectStats projectStats = bugCollection.getProjectStats();
    	Collection<BugInstance> bugs = bugCollection.getCollection();
    	Cloud cloud = bugCollection.getCloud();
    	cloud.setMode(Cloud.Mode.COMMUNAL);
    	
    	out.printf("Cloud sync and summary report for %s%n", bugCollection.getProject().getProjectName());
    	
    	out.printf("Code dated %s%n", new Date(bugCollection.getTimestamp()));
    	out.printf("Code analyzed %s%n", new Date(bugCollection.getAnalysisTimestamp()));
    	
    	out.printf("%6d total classes%n", projectStats.getNumClasses());
    	out.printf("%6d total issues%n", bugs.size());
    	long recentTimestamp = System.currentTimeMillis() - options.ageInHours * 3600 * 1000L;
    	int allRecentIssues = 0;
    	
    	for(BugInstance b : bugs) {
    		Stats s = stats.get(BugRankCategory.getRank(b.getBugRank()));
    		if (s == null) {
    			s = new Stats();
    			stats.put(BugRankCategory.getRank(b.getBugRank()), s);
    		}
    		s.total++;
    		long firstSeen = cloud.getFirstSeen(b);
			if (firstSeen > recentTimestamp) {
    			s.recent++;
    			allRecentIssues++;
    		}
		
    	}
    	out.printf("%6d recent issues%n", allRecentIssues);
    	
    	
    	
    	if (options.cloudSummary != null && cloud.supportsCloudSummaries()) {
    		try {
				PrintWriter cs = new PrintWriter(new FileWriter(options.cloudSummary));
				cs.printf("%6s %6s %s%n", "recent", "total", "Rank category");
		    	for(Entry<BugRankCategory, Stats> e : stats.entrySet()) {
		    		Stats s = e.getValue();
		    		if (s.total > 0)
		    		  cs.printf("%6d %6d %s%n", s.recent, s.total, e.getKey());
		    	}
		    	cs.println();
				cloud.printCloudSummary(cs, bugs, null);
				cs.close();
			} catch (Exception e) {
				out.println("Error writing cloud summary to " + options.cloudSummary);
    			e.printStackTrace(out);
    		}
    	
    		
    	}
    
    }
    public void shutdown()  {
    	Cloud cloud = bugCollection.getCloud();
    	cloud.shutdown();
    }
  

}

@@ -5220,33 +5220,33 @@
   %09out.printf(%22%25
-6
+7
 d total classes%25
@@ -5298,17 +5298,17 @@
 rintf(%22%25
-6
+7
 d total 
@@ -5860,17 +5860,17 @@
 rintf(%22%25
-6
+7
 d recent

increase to 7 digits