/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package usda.weru.weps.reports;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.List;
import net.sf.jasperreports.engine.JRAbstractChartCustomizer;
import net.sf.jasperreports.engine.JRChart;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.AxisState;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPosition;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.CategoryTick;
import org.jfree.chart.entity.CategoryLabelEntity;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.data.category.CategoryDataset;

import org.jfree.data.xy.XYDataset;
import org.jfree.text.TextBlock;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.RectangleEdge;

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

    public static final String PARAMETER_TYPE = "QUICKPLOT_TYPE";
    public static final String PARAMETER_DATASET = "QUICKPLOT_DATASET";

    public enum Type {

        Line("Line", "line"),
        Bar("Bar", "bar"),
        BarStacked("Bar Stacked", "barstacked"),
        Area("Area", "area"),
        Scatter("Scatter", "scatter");
        private final String title;
        private final String key;

        private Type(String title, String key) {
            this.title = title;
            this.key = key;
        }

        public String title() {
            return title;
        }

        public String key() {
            return key;
        }
    }

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

        Object o = getParameterValue(PARAMETER_DATASET);
        if (o instanceof XYDataset) {
            jfc.getXYPlot().setDataset((XYDataset) o);
        } else if (o instanceof CategoryDataset) {




            CategoryAxis axis2 = new CategoryAxis() {


                /**
                 * Draws the category labels and returns the updated axis state.
                 *
                 * @param g2  the graphics device (<code>null</code> not permitted).
                 * @param plotArea  the plot area (<code>null</code> not permitted).
                 * @param dataArea  the area inside the axes (<code>null</code> not
                 *                  permitted).
                 * @param edge  the axis location (<code>null</code> not permitted).
                 * @param state  the axis state (<code>null</code> not permitted).
                 * @param plotState  collects information about the plot (<code>null</code>
                 *                   permitted).
                 *
                 * @return The updated axis state (never <code>null</code>).
                 */
                @Override
                protected AxisState drawCategoryLabels(Graphics2D g2,Rectangle2D plotArea,Rectangle2D dataArea,RectangleEdge edge,AxisState state,PlotRenderingInfo plotState) {

                    if (state == null) {
                        throw new IllegalArgumentException("Null 'state' argument.");
                    }

                    if (isTickLabelsVisible()) {
                        List ticks = refreshTicks(g2, state, plotArea, edge);
                        state.setTicks(ticks);

                        int categoryIndex = 0;
                        Iterator iterator = ticks.iterator();
                        
                        //keep track of the last drawn label
                        Area lastDrawnLabel = null;
                        while (iterator.hasNext()) {

                            CategoryTick tick = (CategoryTick) iterator.next();
                            g2.setFont(getTickLabelFont(tick.getCategory()));
                            g2.setPaint(getTickLabelPaint(tick.getCategory()));

                            CategoryLabelPosition position = this.getCategoryLabelPositions().getLabelPosition(edge);
                            double x0 = 0.0;
                            double x1 = 0.0;
                            double y0 = 0.0;
                            double y1 = 0.0;
                            if (edge == RectangleEdge.TOP) {
                                x0 = getCategoryStart(categoryIndex, ticks.size(),dataArea, edge);
                                x1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,edge);
                                y1 = state.getCursor() - this.getCategoryLabelPositionOffset();
                                y0 = y1 - state.getMax();
                            } else if (edge == RectangleEdge.BOTTOM) {
                                x0 = getCategoryStart(categoryIndex, ticks.size(),dataArea, edge);
                                x1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,edge);
                                y0 = state.getCursor() + this.getCategoryLabelPositionOffset();
                                y1 = y0 + state.getMax();
                            } else if (edge == RectangleEdge.LEFT) {
                                y0 = getCategoryStart(categoryIndex, ticks.size(),dataArea, edge);
                                y1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,edge);
                                x1 = state.getCursor() - this.getCategoryLabelPositionOffset();
                                x0 = x1 - state.getMax();
                            } else if (edge == RectangleEdge.RIGHT) {
                                y0 = getCategoryStart(categoryIndex, ticks.size(),dataArea, edge);
                                y1 = getCategoryEnd(categoryIndex, ticks.size(), dataArea,edge);
                                x0 = state.getCursor() + this.getCategoryLabelPositionOffset();
                                x1 = x0 - state.getMax();
                            }
                            Rectangle2D area = new Rectangle2D.Double(x0, y0, (x1 - x0), (y1 - y0));
                            Point2D anchorPoint = RectangleAnchor.coordinates(area,position.getCategoryAnchor());
                            TextBlock block = tick.getLabel();
                            Shape bounds = block.calculateBounds(g2,(float) anchorPoint.getX(), (float) anchorPoint.getY(),position.getLabelAnchor(), (float) anchorPoint.getX(),(float) anchorPoint.getY(), position.getAngle());
                            Area labelArea = new Area(bounds);
                            
                            if(lastDrawnLabel == null || !lastDrawnLabel.intersects(area) ){
                                block.draw(g2, (float) anchorPoint.getX(),(float) anchorPoint.getY(), position.getLabelAnchor(),(float) anchorPoint.getX(), (float) anchorPoint.getY(),position.getAngle());                            
                                lastDrawnLabel = labelArea;
                            }
                            if (plotState != null && plotState.getOwner() != null) {
                                EntityCollection entities = plotState.getOwner().getEntityCollection();
                                if (entities != null) {
                                    String tooltip = getCategoryLabelToolTip(tick.getCategory());
                                    entities.add(new CategoryLabelEntity(tick.getCategory(),bounds, tooltip, null));
                                }
                            }
                            categoryIndex++;
                        }

                        if (edge.equals(RectangleEdge.TOP)) {
                            double h = state.getMax() + this.getCategoryLabelPositionOffset();
                            state.cursorUp(h);
                        } else if (edge.equals(RectangleEdge.BOTTOM)) {
                            double h = state.getMax() + this.getCategoryLabelPositionOffset();
                            state.cursorDown(h);
                        } else if (edge == RectangleEdge.LEFT) {
                            double w = state.getMax() + this.getCategoryLabelPositionOffset();
                            state.cursorLeft(w);
                        } else if (edge == RectangleEdge.RIGHT) {
                            double w = state.getMax() + this.getCategoryLabelPositionOffset();
                            state.cursorRight(w);
                        }
                    }
                    return state;
                }
            };

            axis2.setCategoryLabelPositions(CategoryLabelPositions.UP_90);


            jfc.getCategoryPlot().setDomainAxis(axis2);



            jfc.getCategoryPlot().setDataset((CategoryDataset) o);




        }

    }
}
