/*
 * -------------------------------------------------------------------------
 *      $Id: RAPanel.java,v 1.2 2006/02/17 16:42:12 estewart Exp $
 * -------------------------------------------------------------------------
 *      Copyright (c) 2004 Visual Numerics Inc. All Rights Reserved.
 *
 *      This software is confidential information which is proprietary to
 *      and a trade secret of Visual Numerics, Inc.  Use, duplication or
 *      disclosure is subject to the terms of an appropriate license
 *      agreement.
 *
 *      VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 *      SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 *      BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 *      FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL
 *      NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 *      AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
 *      ITS DERIVATIVES.
 *--------------------------------------------------------------------------
 */

package com.imsl.demo.stats;
import com.imsl.chart.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.Color;

public class RAPanel extends JPanel implements java.awt.event.ItemListener {
    private JFrame parentFrame;
    private JPanelChart jPanelChart;
    private JCheckBox jCheckBox[];
    private ArrayList carList;
    private int carListSize;
    private String categoryNames[], entryNames[];
    private double categoryValues[][];
    private boolean activeEntries[];
    private double theta[];
    private Data dataEntry[], dataCategory[];
    private Polar axis;
    final private double offset[] = new double[] {1.02};
    Color categoryColors[] = new Color[] {Color.blue, Color.orange, Color.red,
        Color.magenta, Color.black, Color.green, Color.cyan, Color.pink};

    public RAPanel(javax.swing.JFrame parent) {
        this.parentFrame = parent;

        readFile("cardata.csv");
        carListSize = carList.size();

        initComponents();
        setPreferredSize(new java.awt.Dimension(parent.getSize().width, (int)(0.85*parent.getSize().height)));
        jPanelChart.setPreferredSize(new java.awt.Dimension(parent.getSize().width, (int)(0.66*parent.getSize().height)));
        jPanelChart.setChart(new Chart());

        categoryNames = new String[] {"Price", "Acceleration", "Braking", "Grip", "Fuel Economy", ""};
        int numCat = categoryNames.length-1;

        entryNames = new String[carListSize];
        categoryValues = new double[carListSize][numCat];
        activeEntries = new boolean[carListSize];
        for (int i=0; i<carListSize; i++) {
            CarInfo nextCar = (CarInfo)carList.get(i);
            entryNames[i] = nextCar.name;
            double[] vals = nextCar.getValues();
            System.arraycopy(vals, 0, categoryValues[i], 0, vals.length);
            if (i<4) activeEntries[i] = true;
        }

        Chart chart = jPanelChart.getChart();
        axis = new Polar(chart);
        drawGraph();
    }

    public void drawGraph() {
        int numCat = categoryNames.length-1;
        int numberActiveEntries = 0;
        for (int i=0; i<jCheckBox.length; i++) {
            activeEntries[i] = jCheckBox[i].isSelected();
            if (activeEntries[i]) numberActiveEntries++;
        }

        theta = new double[numCat+1];
        dataEntry = new Data[carListSize];
        dataCategory = new Data[numCat+1];

        // set up R axis (0 to 100%)
        axis.getAxisR().setAutoscaleOutput(Axis.AUTOSCALE_OFF);
        axis.getAxisR().setWindow(1.0);
        axis.getAxisR().setTickInterval(0.5);
        axis.getAxisR().setPaint(false);
        //axis.getAxisR().getLegend().setPaint(true);

        //set up Theta axis (0 to 2pi, offset 1/2pi)
        axis.getAxisTheta().setAutoscaleOutput(Axis.AUTOSCALE_OFF);
        axis.getAxisTheta().setWindow(Math.PI/2, Math.PI*2.5);
        axis.getAxisTheta().setNumber(numCat+1);
        axis.getAxisTheta().setPaint(false);

        //distance away from outer axis
        double pointR[] = {0.98};

        //build category items
        for (int i=0; i<numCat+1; i++) {
            theta[i] = Math.PI*2/numCat*i + Math.PI*0.5;
            dataCategory[i] = new Data(axis, pointR, new double[] {theta[i]});
            dataCategory[i].setLabelType(Data.LABEL_TYPE_TITLE);
            dataCategory[i].setTitle(categoryNames[i]);
            dataCategory[i].setFontStyle(1);
            dataCategory[i].getTitle().setAlignment(getTitleLocation(theta[i]));
        }

        //build entry elements
        for (int j=0; j<carListSize; j++) {
            //System.out.println(j+","+theta.length+","+categoryValues[j].length);
            double activeCats[] = new double[categoryValues[j].length+1];
            System.arraycopy(categoryValues[j], 0, activeCats, 0, categoryValues[j].length);
            activeCats[categoryValues[j].length] = categoryValues[j][0];

            //dataEntry[j] = new Data(axis, categoryValues[j], theta);
            dataEntry[j] = new Data(axis, activeCats, theta);
            dataEntry[j].setDataType(Data.DATA_TYPE_MARKER|Data.DATA_TYPE_LINE);
            dataEntry[j].setMarkerType(Data.MARKER_TYPE_FILLED_SQUARE);
            dataEntry[j].setLineColor(categoryColors[j]);
            dataEntry[j].setMarkerColor(categoryColors[j]);
            dataEntry[j].setTitle(entryNames[j]);
            dataEntry[j].setPaint(activeEntries[j]);
        }
        repaint();
    }

    public void updateGraph() {
        for (int j=0; j<dataEntry.length; j++) {
            if (dataEntry[j]!=null) dataEntry[j].remove();
        }
        for (int j=0; j<dataCategory.length; j++) {
            if (dataCategory[j]!=null) dataCategory[j].remove();
        }
        drawGraph();
        repaint();
    }

    public void itemStateChanged(java.awt.event.ItemEvent e) {
        updateGraph();
    }

    private void readFile(String file) {
        try {
            InputStream is = getClass().getResourceAsStream(file);
            //FileInputStream is = new FileInputStream(file);
            Reader fr = new InputStreamReader(is);
            LineNumberReader lnr = new LineNumberReader(fr);
            int lineNum = 0;

            carList = new ArrayList();

            while (true) {
                String line = lnr.readLine();
                if (line == null)  break;
                lineNum++;
                StringTokenizer st = new StringTokenizer(line,",");

                String name = st.nextToken();
                double price = Double.valueOf(st.nextToken()).doubleValue();
                double acc = Double.valueOf(st.nextToken()).doubleValue();
                double brak = Double.valueOf(st.nextToken()).doubleValue();
                double grip = Double.valueOf(st.nextToken()).doubleValue();
                double mpg = Double.valueOf(st.nextToken()).doubleValue();
                carList.add(new CarInfo(name, price, acc, brak, grip, mpg));
            }
        } catch (IOException ioe) {
            System.out.println(ioe.getMessage());
            ioe.printStackTrace();
        }
    }

    // return the position of the entry based on theta
    private int getTitleLocation(double theta) {
        int temp = 0;

        // constant field values from com.imsl.chart.Chartnode
        if (theta >= 1.50 && theta < 1.64) { temp = Data.TEXT_Y_BOTTOM|Data.TEXT_X_CENTER; }
        if (theta >= 1.64 && theta < 3.00) { temp = Data.TEXT_Y_BOTTOM|Data.TEXT_X_RIGHT; }
        if (theta >= 3.00 && theta < 3.28) { temp = Data.TEXT_Y_CENTER|Data.TEXT_X_RIGHT; }
        if (theta >= 3.28 && theta < 4.64) { temp = Data.TEXT_Y_TOP|Data.TEXT_X_RIGHT; }
        if (theta >= 4.64 && theta < 4.78) { temp = Data.TEXT_Y_TOP|Data.TEXT_X_CENTER; }
        if (theta >= 4.78 && theta < 6.21) { temp = Data.TEXT_Y_TOP|Data.TEXT_X_LEFT; }
        if (theta >= 6.21 && theta < 6.29) { temp = Data.TEXT_Y_CENTER|Data.TEXT_X_LEFT; }
        if (theta >= 6.29 && theta < 7.78) { temp = Data.TEXT_Y_BOTTOM|Data.TEXT_X_LEFT; }

        return temp;
    }

    private void initComponents() {
        setLayout(new java.awt.BorderLayout());

        // add the check box to select cars on the EAST side
        JPanel checkPanel = new JPanel();
        String details = "<html><hr><b><u>Data Details</u></b><br>"+
                         "<b>Price</b>: Base price, $ / $100,000<br>"+
                          "<b>Acceleration</b>: 0-60 mph, sec / 10 s<br>"+
                          "<b>Braking</b>: 70-0 mph, ft / 200 ft<br>"+
                          "<b>Grip</b>: 300' skid pad, g<br>"+
                          "<b>Fuel</b>: EPA Hwy, mpg / 30 mpg<br>"+
                          "<b>Source</b>: <em>Car and Driver</em></html>";
        JEditorPane jEditorPane = new JEditorPane();
        jEditorPane = new javax.swing.JEditorPane();
        jEditorPane.setContentType("text/html");
        jEditorPane.setEditable(false);
        jEditorPane.setText(details);
        jEditorPane.setCaretPosition(0);

        checkPanel.setLayout(new javax.swing.BoxLayout(checkPanel, javax.swing.BoxLayout.Y_AXIS));
        JLabel jLabel = new JLabel("Select cars to compare\n");
        checkPanel.add(jLabel);
        jCheckBox = new JCheckBox[carListSize];
        for (int i=0; i<carListSize; i++) {
            jCheckBox[i] = new JCheckBox(((CarInfo)carList.get(i)).name);
            if (i<4) jCheckBox[i].setSelected(true);
            jCheckBox[i].setForeground(categoryColors[i]);
            jCheckBox[i].setBackground(jEditorPane.getBackground());
            checkPanel.add(jCheckBox[i]);
            jCheckBox[i].addItemListener(this);
        }
        checkPanel.setBackground(jEditorPane.getBackground());
        checkPanel.add(jEditorPane);
        add(checkPanel, java.awt.BorderLayout.EAST);

        jPanelChart = new JPanelChart();
        jPanelChart.setPreferredSize(new java.awt.Dimension(500, 500));
        add(jPanelChart, java.awt.BorderLayout.CENTER);
    }

    class CarInfo {
        String name;
        double price;
        double acceleration;
        double braking;
        double roadholding;
        double economy;

        CarInfo(String n, double p, double a, double b, double r, double e) {
            this.name = n;
            this.price = p;
            this.acceleration = a;
            this.braking = b;
            this.roadholding = r;
            this.economy = e;
        }

        double[] getValues() {
            return new double[] {price, acceleration, braking, roadholding, economy};
        }
    }
}