package org.jenkinsci.plugins.codedx;

import hudson.util.ChartUtil.NumberOnlyBuildLabel;
import hudson.util.DataSetBuilder;
import hudson.util.ShiftedCategoryAxis;

import java.awt.Color;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;

import org.jenkinsci.plugins.codedx.model.CodeDxGroupStatistics;
import org.jenkinsci.plugins.codedx.model.StatisticGroup;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;

import org.jfree.data.category.CategoryDataset;
import org.jfree.ui.RectangleInsets;

/**
 *
 * @author ademartini This file is heavily derived from the sloccount-plugin (author: lordofthepigs)
 */
public class CodeDxChartBuilder implements Serializable {
    /** Serial version UID. */
    private static final long serialVersionUID = 0L;

    private CodeDxChartBuilder(){
    }

    public static JFreeChart buildChart(CodeDxBuildAction action,
            int numBuildsInGraph, String statisticsName, Map<String,Color> colors){

    	CategoryDataset dataset = buildDataset(action, numBuildsInGraph, statisticsName);
    	
        JFreeChart chart = ChartFactory.createStackedAreaChart(null, null,
                "Findings", dataset,
                PlotOrientation.VERTICAL, true, false, true);

        chart.setBackgroundPaint(Color.white);

        CategoryPlot plot = chart.getCategoryPlot();
        plot.setBackgroundPaint(Color.WHITE);
        plot.setOutlinePaint(null);
        plot.setForegroundAlpha(0.8f);
        plot.setRangeGridlinesVisible(true);
        plot.setRangeGridlinePaint(Color.black);
       
        CategoryAxis domainAxis = new ShiftedCategoryAxis(null);
        plot.setDomainAxis(domainAxis);
        domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);
        domainAxis.setLowerMargin(0.0);
        domainAxis.setUpperMargin(0.0);
        domainAxis.setCategoryMargin(0.0);

        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());

        // crop extra space around the graph
        plot.setInsets(new RectangleInsets(0, 0, 0, 5.0));

        
        List rows = dataset.getRowKeys();
        
        List<Color> colorList = new ArrayList<Color>();
         	
        if(colors != null){
        	
            for(Object row : rows){
            	
            	if(colors.containsKey(row.toString())){
            		
            		colorList.add(colors.get(row.toString()));
            	}
            }
        }

        if(colorList.size() == rows.size()){
        
            plot.setRenderer(new CodeDxAreaRenderer(colorList));
        }
        else{
        	
            plot.setRenderer(new CodeDxAreaRenderer(null));
        }
       
        return chart;
    }

    private static CategoryDataset buildDataset(CodeDxBuildAction lastAction,
            int numBuildsInGraph, String statisticsName){
        DataSetBuilder<StatisticGroup, NumberOnlyBuildLabel> builder = new DataSetBuilder<StatisticGroup, NumberOnlyBuildLabel>();
        Set<StatisticGroup> allGroups = new HashSet<StatisticGroup>();

        CodeDxBuildAction action = lastAction;
        int numBuilds = 0;

        // numBuildsInGraph <= 1 means unlimited
        while(action != null && (numBuildsInGraph <= 1 || numBuilds < numBuildsInGraph)){
            CodeDxResult result = action.getResult();
            if(result != null){
                NumberOnlyBuildLabel buildLabel = new NumberOnlyBuildLabel(action.getBuild());

                for (String group : result.getStatistics(statisticsName).getAllGroups()) {
                    allGroups.add(StatisticGroup.forValue(group));
                }
                Set<StatisticGroup> remainingGroups = StatisticGroup.valuesForStatistic(statisticsName);

                for(CodeDxGroupStatistics groupStats : result.getStatistics(statisticsName).getStatistics()){
                    builder.add(groupStats.getFindings(), StatisticGroup.forValue(groupStats.getGroup()), buildLabel);
                    remainingGroups.remove(StatisticGroup.forValue(groupStats.getGroup()));
                }
                
                for(StatisticGroup group : remainingGroups) {
                    builder.add(0, group, buildLabel);
                }

                ++numBuilds;
            }

            action = action.getPreviousAction();
        }

        return builder.build();
    }


}
@@ -456,16 +456,96 @@
 eChart;%0A
+import org.jfree.chart.LegendItem;%0Aimport org.jfree.chart.LegendItemCollection;%0A
 import o
@@ -3035,24 +3035,712 @@
 ;%0A        %7D%0A
+%0A%0A        ArrayList%3CLegendItem%3E legendItems = new ArrayList%3CLegendItem%3E();%0A        Iterator%3CLegendItem%3E itr = plot.getLegendItems().iterator();%0A        while (itr.hasNext()) %7B%0A            legendItems.add(itr.next());%0A        %7D%0A        //Reverse the order%0A        Collections.sort(legendItems, new Comparator%3CLegendItem%3E() %7B%0A            public int compare(LegendItem lhs, LegendItem rhs) %7B%0A                return rhs.getSeriesKey().compareTo(lhs.getSeriesKey());%0A            %7D%0A        %7D);%0A        LegendItemCollection newItems = new LegendItemCollection();%0A        for (LegendItem item : legendItems) %7B%0A            newItems.add(item);%0A        %7D%0A        plot.setFixedLegendItems(newItems);%0A
        %0A    

Update order for the chart legends