package usda.weru.weps.reports;

import java.awt.BasicStroke;
import java.awt.Color;
import net.sf.jasperreports.engine.JRAbstractChartCustomizer;
import net.sf.jasperreports.engine.JRChart;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.LegendItem;
import org.jfree.chart.LegendItemCollection;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.DeviationRenderer;
import org.jfree.chart.renderer.xy.XYStepRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.data.xy.YIntervalSeries;
import org.jfree.data.xy.YIntervalSeriesCollection;
import org.jfree.ui.RectangleInsets;
import usda.weru.util.ConfigData;
import usda.weru.util.Util;

/**
 *
 * @author Joseph Levin <joelevin@weru.ksu.edu>
 */
public class ConfidenceIntervalChartCustomizer extends JRAbstractChartCustomizer {

    /**
     *
     * @param jfc
     * @param jrc
     */
    @Override
    public void customize(JFreeChart jfc, JRChart jrc) {

        if (jfc.getPlot() instanceof XYPlot) {
            XYPlot plot = (XYPlot) jfc.getPlot();
            
            XYDataset data = plot.getDataset();

            int lowIndex = data.indexOf("low");
            int runningIndex = data.indexOf("running");
            int highIndex = data.indexOf("high");

            int lossIndex = data.indexOf("loss");
            int lossMinIndex = data.indexOf("loss_min");
            int lossMaxIndex = data.indexOf("loss_max");

            YIntervalSeries ciSeries = new YIntervalSeries("Average", true, true);
//            YIntervalSeries lossSeries = new YIntervalSeries("Gross Loss", true, true);
            XYSeries lossSeries = new XYSeries("Cycle Average", true, true);
            boolean first = true;
            boolean skipped = false;
            double archiveHigh = 0.0;
            double archiveCyc = 0.0;
            double archiveY = 0.0;
            double archiveLow = 0.0;
            double lossMax = 0.0;
            for (int i = 0; i < data.getItemCount(runningIndex); i++) {
                int cycleRunning = data.getX(runningIndex, i).intValue();
                double y = data.getYValue(runningIndex, i);
                double low = data.getYValue(lowIndex, i);
                double high = data.getYValue(highIndex, i);
                
                ciSeries.add(cycleRunning, y, low, high);
                
                int cycleLoss = data.getX(lossIndex, i).intValue();
                double loss = data.getYValue(lossIndex, i);
                lossMax = Math.max(loss, lossMax);

//                lossSeries.add(cycleLoss, loss, lossMin, lossMax);                
                lossSeries.add(cycleLoss, loss);
            }

            YIntervalSeriesCollection ciDataset = new YIntervalSeriesCollection();
            ciDataset.addSeries(ciSeries);
            plot.setDataset(0, ciDataset);

            XYSeriesCollection lossDataset = new XYSeriesCollection();
            lossDataset.addSeries(lossSeries);
            plot.setDataset(1, lossDataset);

            plot.getDomainAxis().setLabel("Rotation Cycles");
            if (Util.USUnits.equals(ConfigData.getDefault().getData(ConfigData.Units))) {
                plot.getRangeAxis().setLabel("tn/ac");
            } else {
                plot.getRangeAxis().setLabel("kg/m\u00B2");
            }

            //don't require zero when auto ranging            
            setupAutoRange(plot.getDomainAxis());
            setupAutoRange(plot.getRangeAxis());

            // deviation rendering
            DeviationRenderer devRenderer = new DeviationRenderer(true, true);
            devRenderer.setSeriesFillPaint(0, new Color(0, 255, 0, 191));
            devRenderer.setSeriesStroke(0, new BasicStroke(2f));
            devRenderer.setSeriesShapesVisible(0, false);
            devRenderer.setSeriesOutlinePaint(0, Color.BLACK);

            devRenderer.setSeriesStroke(1, new BasicStroke(1));
            devRenderer.setSeriesShapesVisible(1, false);

            plot.setRenderer(0, devRenderer);

            // bar plot rendering
            XYStepRenderer stepRenderer = new XYStepRenderer();
//            barRenderer.setShadowVisible(false);
            stepRenderer.setSeriesPaint(0, new Color(0, 0, 255, 150));
            plot.setRenderer(1, stepRenderer);
            
            double maxRange = lossMax > 1.0 ? Math.ceil(lossMax) : Math.ceil(10.0 * lossMax) / 10.0;
            plot.getRangeAxis().setRange(0.0, maxRange);

            LegendItemCollection items = new LegendItemCollection();
            items.addAll(plot.getLegendItems());
            items.add(new LegendItem("90% Confidence", new Color(0, 255, 0, 191)));
            //items.add(new LegendItem("Cycle Range", new Color(0, 0, 255, 100)));    
            plot.setFixedLegendItems(items);

            //enable the border
            jfc.setBorderVisible(true);

            // padding
            jfc.setPadding(new RectangleInsets(5, 10, 5, 5));

            plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

        }
    }

    private void setupAutoRange(ValueAxis axis) {
        if (axis instanceof NumberAxis) {
            NumberAxis number = (NumberAxis) axis;
            number.setAutoRangeIncludesZero(false);
            number.setAutoRangeStickyZero(false);

            number.setAutoRange(true);

        }
    }
}
