/*
 * Licensed Materials - Property of Rogue Wave Software, Inc. 
 * © Copyright Rogue Wave Software, Inc. 2014, 2015 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */
package radar;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import ilog.views.chart.IlvChart;
import ilog.views.chart.IlvChartRenderer;
import ilog.views.chart.IlvColor;
import ilog.views.chart.IlvLegend;
import ilog.views.chart.IlvRendererLegendItem;
import ilog.views.chart.IlvStyle;
import ilog.views.chart.data.IlvDataSet;
import ilog.views.chart.data.IlvDataSource;
import ilog.views.chart.data.IlvDefaultDataSource;
import ilog.views.chart.event.LegendEvent;
import ilog.views.chart.event.LegendListener;
import ilog.views.chart.renderer.IlvAreaChartRenderer;
import ilog.views.chart.renderer.IlvBarChartRenderer;
import ilog.views.chart.renderer.IlvPolylineChartRenderer;
import ilog.views.chart.renderer.IlvSinglePolylineRenderer;
import ilog.views.chart.graphic.IlvMarkerFactory;
import ilog.views.util.java2d.IlvPattern;

import shared.*;

/**
 * An example showing a Cartesian chart and a Radar chart displaying the
 * same data.
 */
public class RadarDemo extends AbstractChartExample implements ActionListener
{
    static final int DSCOUNT        = 4;
    static final int STANDARD       = 1;
    static final int STACKED        = 2;
    static final int STACKED100     = 3;

    int                         displayType = STANDARD;
    IlvBarChartRenderer         cartRenderer;
    IlvPolylineChartRenderer    radarRenderer;
    IlvChart                    cartChart;
    IlvChart                    radarChart;

    /**
     * A legend listener that modifies the rendering styles
     * of chart renderers when the user clicks on items.
     */
    class Selector implements LegendListener {

        IlvChartRenderer selected   = null;
        IlvStyle         savedStyle = null;

        /**
         * Invoked when the user has clicked on an item.
         */
        public void itemClicked(LegendEvent evt)
        {
            IlvRendererLegendItem item = (IlvRendererLegendItem) evt.getItem();
            select(item.getRenderer());
        }

        /**
         * Selects the specified renderer.
         * Previously selected renderers are unselected.
         */
        void select(IlvChartRenderer r)
        {
            unselect();
            if (selected == r) {
                selected = null;
                return;
            }
            IlvStyle style = r.getStyle(0);
            selected = r;
            savedStyle = style;
            Color fillColor   = style.getFillColor();
            Color strokeColor = style.getStrokeColor();
            if (fillColor == null || strokeColor == null)
                return;
            IlvPattern pattern = new IlvPattern(IlvPattern.DOWN_LIGHT_DIAGONAL,
                                                Color.darkGray, fillColor);
            r.setStyle(0, style.setFillPaint(pattern).setStrokePaint(Color.black));

            IlvDataSet dataSet = r.getDataSource().getDataSet(0);
            IlvSinglePolylineRenderer poly = radarRenderer.getPolyline(dataSet);
            if (poly != null) {
                poly.setMarker(IlvMarkerFactory.getSquareMarker());
                poly.setMarkerSize(3);
                poly.setMarkerStyle(new IlvStyle(Color.black, Color.white));
            }
        }

        /**
         * Unselects renderers.
         */
        void unselect()
        {
            if (selected == null)
                return;
            selected.setStyle(0, savedStyle);
            IlvDataSet dataSet = selected.getDataSource().getDataSet(0);
            IlvSinglePolylineRenderer poly = radarRenderer.getPolyline(dataSet);
            if (poly != null)
                poly.setMarker(null);
        }
    }

    /**
     * Initializes the example's user interface in the specified container.
     * @param container The <code>contentPane</code> of the <code>JApplet</code>
     * or the <code>JFrame</code>, depending on how the demo is run.
     */
    public void init(Container container)
    {
        super.init(container);
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1,0));
        container.add(panel, BorderLayout.CENTER);
        panel.setBackground(new Color(180, 180, 180));

        // The data that will be displayed by both charts.
        double[][] data = new double[][]
        {
            {1.83, 2.18, 2.77, 4.50, 4.88, 2.88, 2.31, 2.21, 3.39, 3.52, 2.29, 1.84},
            {2.11, 1.44, 6.69, 6.83, 8.00, 2.41, 3.45, 1.5, 1.54, 0.75, 0.74, 2.07},
            {0.97, 0.95, 2.36, 3.14, 2.03, 3.42, 3.85, 5.02, 1.51, 6.56, 5.54, 0.47},
            {1.44, 0.48, 3.84, 2.74, 6.91, 0.99, 0.77, 1., 2.30, 2.26, 2.42, 2.55}
        };

        String[] names      = { "Norm", "1998", "1999", "2000"};
        String[] dataLabels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
        IlvDataSource dataSource
            = new IlvDefaultDataSource(data, -1, names, dataLabels);

        //== Create a Cartesian chart.
        cartChart  = new IlvChart(IlvChart.CARTESIAN);
        cartRenderer = new IlvBarChartRenderer();
        cartRenderer.setDataSource(dataSource);
        cartRenderer.setStyles(getCartStyles());
        cartChart.addRenderer(cartRenderer);
        cartChart.getXScale().setCategory(dataSource.getDataSet(0), true);
        cartChart.getXScale().setSkippingLabel(true);
        configureChart(cartChart);

        //== Create a Radar chart.
        radarChart = new IlvChart(IlvChart.RADAR);
        radarRenderer = new IlvAreaChartRenderer();
        radarRenderer.setDataSource(dataSource);
        IlvStyle[] styles = getRadarStyles();
        radarRenderer.setStyles(styles);
        radarChart.addRenderer(radarRenderer);
        radarChart.getXGrid().setMajorStroke(
            new BasicStroke(2.f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        radarChart.getXGrid().setMajorPaint(Color.black);
        radarChart.getYGrid(0).setMajorPaint(Color.lightGray);
        radarChart.setAntiAliasing(true);
        radarChart.getXScale().setCategory(dataSource.getDataSet(0), false);
        configureChart(radarChart);

        cartChart.getYScale(0).setTitle("Rain fall (mm)", 270);

        panel.add(cartChart);
        panel.add(radarChart);

        container.add(createTopPanel(), BorderLayout.NORTH);
    }

    /**
     * Creates a panel containing the legend and configuration panel.
     */
    JPanel createTopPanel()
    {
        JPanel topPanel = new JPanel(new GridLayout(1, 2));
        topPanel.setBorder(BorderFactory.createEtchedBorder());


        JPanel legendPanel = new JPanel();
        IlvLegend legend = new IlvLegend();
        legend.addLegendListener(new Selector());
        legend.setLayout(new FlowLayout(FlowLayout.LEFT, 8, 0));
        legend.setBorder(null);
        cartChart.setLegend(legend);
        legendPanel.add(legend);
        legendPanel.setBorder(BorderFactory.createTitledBorder("Years  (Click on an item to select)"));
        topPanel.add(legendPanel);

        ConfigPanel configPanel = new ConfigPanel();
        configPanel.setOpaque(false);
        configPanel.addActionListener(this);
        topPanel.add(configPanel);

        return topPanel;
    }

    /**
     * Returns the styles for the renderer in the Radar chart.
     */
    IlvStyle[] getRadarStyles()
    {
        IlvStyle[] styles = new IlvStyle[DSCOUNT];
        Color[] colors    = IlvColor.generateColors(DSCOUNT);
        Stroke stroke
            = new BasicStroke(3.f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
        for (int i=0; i<DSCOUNT; ++i) {
            Color strokeColor = colors[i];
            Color fillColor = IlvColor.setAlpha(strokeColor, .4f);
            styles[i] = new IlvStyle(stroke, strokeColor, fillColor);
        }
        return styles;
    }

    /**
     * Returns the styles for the renderer in the Cartesian chart.
     */
    IlvStyle[] getCartStyles()
    {
        Color[] colors       = IlvColor.generateColors(DSCOUNT);
        IlvStyle[] styles    = new IlvStyle[DSCOUNT];
        for (int i=0; i<DSCOUNT; ++i) {
            styles[i] = new IlvStyle(IlvColor.darker(colors[i]), colors[i]);
        }
        return styles;
    }

    /**
     * <code>ActionListener</code> implementation: connected to the controls of the
     * <code>ConfigPanel</code>.
     * This method changes the display mode of the renderers.
     */
    public void actionPerformed(ActionEvent evt)
    {
        String title = null;
        if (evt.getActionCommand().equals(ConfigPanel.STANDARD_CMD)) {
            cartRenderer.setMode(IlvBarChartRenderer.CLUSTERED);
            radarRenderer.setMode(IlvPolylineChartRenderer.SUPERIMPOSED);
            title = "Rain fall (mm)";
        } else if (evt.getActionCommand().equals(ConfigPanel.STACKED_CMD)) {
            cartRenderer.setMode(IlvBarChartRenderer.STACKED);
            cartRenderer.setStacked100Percent(false);
            radarRenderer.setMode(IlvPolylineChartRenderer.STACKED);
            radarRenderer.setStacked100Percent(false);
            title = "Rain fall (mm)";
        } if (evt.getActionCommand().equals(ConfigPanel.STACKED100_CMD)) {
            cartRenderer.setMode(IlvBarChartRenderer.STACKED);
            cartRenderer.setStacked100Percent(true);
            radarRenderer.setMode(IlvPolylineChartRenderer.STACKED);
            radarRenderer.setStacked100Percent(true);
            title = "Rain fall (%) ";
        }
        cartChart.getYScale(0).setTitle(title, 270);
    }

    /**
     * Customizes the chart appearance.
     */
    static void configureChart(IlvChart chart)
    {
        chart.getYAxis(0).setDataMin(0);
        chart.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createEtchedBorder(),
                        BorderFactory.createEmptyBorder(3,3,3,3)));
        chart.setForeground(Color.black);

        // Add an editing interactor
        EditPointInteractor inter = new EditPointInteractor();
        inter.setPrecision(.01);
        chart.addInteractor(inter);

        // Add a footer
        chart.setFooterText("Click on a point to edit");
        chart.getFooter().setOpaque(true);
        chart.getFooter().setBackground(Color.white);
        chart.getFooter().setBorder(BorderFactory.createLineBorder(chart.getFooter().getForeground()));
    }

    /**
     * Application mainline.
     */
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(
            new Runnable() {
              public void run() {
                  JFrame frame = new JFrame("Radar Chart sample");
                  RadarDemo demo = new RadarDemo();
                  demo.init(frame.getContentPane());
                  demo.setFrameGeometry(800, 500, true);
                  frame.setVisible(true);
              }
            });
    }
}