/*
 * -------------------------------------------------------------------------
 *      $Id: EPanel.java,v 1.3 2004/10/11 13:22:29 estewart Exp $
 * -------------------------------------------------------------------------
 *      Copyright (c) 1999 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.
 *--------------------------------------------------------------------------
 */

/*
 * EPanel.java
 *
 * Created on September 14, 2004, 2:46 PM
 */

package com.imsl.demo.heatmaps;

import com.imsl.chart.*;
import com.imsl.stat.Summary;
import java.util.*;
import java.io.*;
import java.awt.event.*;
import java.awt.Color;


public class EPanel extends javax.swing.JPanel implements MouseMotionListener, MouseListener {

    private Chart chart;
    private AxisXY axis;
    private Heatmap heatmap;
    private HashMap map;
    private ProfilePlot pPlot;
    private double[][] data0, data1, data2, plotData;
    private double[] range0, range1, range2, plotRange, dateRange, x;
    private String plotName;
    private boolean showProfile;
    private javax.swing.JFrame parentFrame;
    private final int xMin = 0;
    private final int xMax = 365;
    private final int yMin = 0;
    private final int yMax = 144;


    /** Creates new form EPanel */
    public EPanel(javax.swing.JFrame parent) {
        this.parentFrame = parent;

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

        setChart();
        jPanelChart.addMouseMotionListener(this);
        jPanelChart.addMouseListener(this);
        jPanelChart.setPreferredSize(new java.awt.Dimension(parent.getSize().width, (int)(0.66*parent.getSize().height)));
        try {
            getData();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // compute x values used for profile plots
        x = new double[xMax];
        for (int i=0; i<xMax; i++) {
            x[i] = (new GregorianCalendar(2000, 0, 1+i)).getTimeInMillis();
        }

        plotData = data0;
        update(0);
    }


    private void setChart() {
        chart = jPanelChart.getChart();
        axis = new AxisXY(chart);

        // Set axis ranges
        axis.getAxisX().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        axis.getAxisY().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        axis.getAxisY().setWindow(0.0, yMax-1);
        axis.getAxisX().getAxisTitle().setTitle("Day of Year");
        axis.getAxisY().getAxisTitle().setTitle("Time of Day");

        axis.getAxisX().getAxisLabel().setTextFormat(new java.text.SimpleDateFormat("MMM"));
        dateRange = new double[] {(new java.util.GregorianCalendar(2000, 0, 1)).getTimeInMillis(),
            (new java.util.GregorianCalendar(2000, 11, 31)).getTimeInMillis()};
        axis.getAxisX().setWindow(dateRange);
        axis.getAxisX().setNumber(6);
        axis.getAxisX().setDensity(2);

        String yLabels[] = {"00:00","06:00","12:00","18:00","24:00"};
        axis.getAxisY().setFirstTick(0);
        axis.getAxisY().setTickInterval(36);
        axis.getAxisY().getAxisLabel().setLabels(yLabels);
    }


    // clear and load data sets determined by the menu selection
    public void getData() throws IOException, java.text.ParseException {
        data0 = new double[xMax][yMax];
        data1 = new double[xMax][yMax];
        data2 = new double[xMax][yMax];
        range0 = new double[] {0,0};
        range1 = new double[] {0,0};
        range2 = new double[] {0,0};

        // read first data set
        InputStream is = getClass().getResourceAsStream("temp.csv");
        Reader fr = new InputStreamReader(is);
        LineNumberReader lnr = new LineNumberReader(fr);
        int lineNum = 0;

        while (true) {
            String line = lnr.readLine();
            if (line == null)  break;
            StringTokenizer st = new StringTokenizer(line,",");
            for (int i=0; i<xMax; i++)
               data0[i][lineNum] = Double.valueOf(st.nextToken()).doubleValue();
            lineNum++;
        }
        for (int i=0; i<xMax; i++) {
            double max = Summary.maximum(data0[i]);
            double min = Summary.minimum(data0[i]);
            if (min < range0[0]) range0[0] = min;
            if (max > range0[1]) range0[1] = max;
        }

        // read second data set
        is = getClass().getResourceAsStream("co.csv");
        fr = new InputStreamReader(is);
        lnr = new LineNumberReader(fr);
        lineNum = 0;

        while (true) {
            String line = lnr.readLine();
            if (line == null)  break;
            StringTokenizer st = new StringTokenizer(line,",");
            for (int i=0; i<xMax; i++)
               data1[i][lineNum] = Double.valueOf(st.nextToken()).doubleValue();
            lineNum++;
        }
        for (int i=0; i<xMax; i++) {
            double max = Summary.maximum(data1[i]);
            double min = Summary.minimum(data1[i]);
            if (min < range1[0]) range1[0] = min;
            if (max > range1[1]) range1[1] = max;
        }

        // read third data set
        is = getClass().getResourceAsStream("so2.csv");
        fr = new InputStreamReader(is);
        lnr = new LineNumberReader(fr);
        lineNum = 0;

        while (true) {
            String line = lnr.readLine();
            if (line == null)  break;
            StringTokenizer st = new StringTokenizer(line,",");
            for (int i=0; i<xMax; i++)
               data2[i][lineNum] = Double.valueOf(st.nextToken()).doubleValue();
            lineNum++;
        }
        for (int i=0; i<xMax; i++) {
            double max = Summary.maximum(data2[i]);
            double min = Summary.minimum(data2[i]);
            if (min < range2[0]) range2[0] = min;
            if (max > range2[1]) range2[1] = max;
        }
    }


    // Draw the graph
    private void drawGraph() {
        if (heatmap != null) {
            heatmap.getHeatmapLegend().setPaint(false);
            heatmap.remove();
        }
        heatmap = new Heatmap(axis, dateRange[0], dateRange[1], 0, yMax-1, plotRange[0], plotRange[1], plotData, Colormap.BLUE_GREEN_RED_YELLOW);
        heatmap.getHeatmapLegend().setPaint(true);
        heatmap.getHeatmapLegend().setTextFormat("##");
        heatmap.getHeatmapLegend().setTitle("Value");
    }


    public void setVisible(boolean show) {
        super.setVisible(show);
        if (show) {
            if (pPlot == null) {
                pPlot = new ProfilePlot(parentFrame);
            } else {
                if (showProfile) {
                    pPlot.setVisible(true);
                }
            }
        } else {
            if (pPlot != null) {
                pPlot.setVisible(false);
            }
        }
    }


    private void clearProfile() {
        pPlot.clearData();
    }


    private void plotProfile(int xLoc, int yLoc) {
        if (!pPlot.isVisible()) pPlot.show();
        double[] y = new double[xMax];
        for (int i=0; i<xMax; i++) {
            y[i] = plotData[i][yLoc];
        }
        pPlot.draw(x, y, plotRange, getTimeString(yLoc+1), plotName);
    }


    private String getTimeString(int y) {
        int totalMinutes = y*10;
        int hours = totalMinutes/60;
        int minutes = totalMinutes-hours*60;
        java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
        nf.setMinimumIntegerDigits(2);
        return new String(nf.format(hours)+":"+nf.format(minutes));
    }


    // Redraw the chart based on radio button selection.
    public void update(int dataSet) {
        if (dataSet == 0) {
            plotData = data0;
            plotRange = range0;
            plotName = "Temperature, F";
            jRadioButton1.setSelected(false);
            jRadioButton2.setSelected(false);
        }
        if (dataSet == 1) {
            plotData = data1;
            plotRange = range1;
            plotName = "Carbon Monoxide, ppm";
            jRadioButton0.setSelected(false);
            jRadioButton2.setSelected(false);
        }
        if (dataSet == 2) {
            plotData = data2;
            plotRange = range2;
            plotName = "Sulfur Dioxide, ppm";
            jRadioButton0.setSelected(false);
            jRadioButton1.setSelected(false);
        }
        drawGraph();
        repaint();
    }


    private void initComponents() {
        jPanelTop = new javax.swing.JPanel();
        jPanelLeft = new javax.swing.JPanel();
        jPanelRight = new javax.swing.JPanel();
        jRadioButton0 = new javax.swing.JRadioButton();
        jRadioButton1 = new javax.swing.JRadioButton();
        jRadioButton2 = new javax.swing.JRadioButton();
        jLabelSelect = new javax.swing.JLabel();
        displayText = new javax.swing.JTextArea(6, 20);
        jCheckBox = new javax.swing.JCheckBox();
        jPanelChart = new com.imsl.chart.JPanelChart();

        setLayout(new javax.swing.BoxLayout(this, javax.swing.BoxLayout.Y_AXIS));
        setPreferredSize(new java.awt.Dimension(500, 600));

        jPanelTop.setLayout(new javax.swing.BoxLayout(jPanelTop, javax.swing.BoxLayout.X_AXIS));
        jPanelLeft.setLayout(new javax.swing.BoxLayout(jPanelLeft, javax.swing.BoxLayout.Y_AXIS));

        jLabelSelect.setText("  Select Data Set:    ");
        jPanelLeft.add(jLabelSelect);

        jRadioButton0.setText("Temperature, F");
        jRadioButton0.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                update(0);
            }
        });
        jRadioButton0.setSelected(true);
        jPanelLeft.add(jRadioButton0);

        jRadioButton1.setText("Carbon Monoxide, ppm");
        jRadioButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                update(1);
            }
        });
        jPanelLeft.add(jRadioButton1);

        jRadioButton2.setText("Sulfur Dioxide, ppm");
        jRadioButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                update(2);
            }
        });
        jPanelLeft.add(jRadioButton2);

        jCheckBox.setSelected(false);
        jCheckBox.setText("Show Profile");
        jCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                showProfile = !showProfile;
                if ((!showProfile) && (pPlot.isVisible())) {
                    pPlot.setVisible(false);
                    repaint();
                }
            }
        });
        jPanelRight.add(jCheckBox);

        jPanelTop.add(jPanelLeft);
        jPanelTop.add(jPanelRight);
        add(jPanelTop);

        jPanelChart.setPreferredSize(new java.awt.Dimension(500, 500));
        add(jPanelChart);
    }


    // Implement MouseMotionListener
    public void mouseMoved(MouseEvent e) {
        double user[] = {0,0};
        axis.mapDeviceToUser(e.getX(), e.getY(), user);
        if ((user[0] < dateRange[0]) || (user[0] > dateRange[1]) ||
            (user[1] < yMin) || (user[1] > yMax)) {

            if (showProfile) clearProfile();
            return;
        }

        if (showProfile) plotProfile((int)user[0],(int)user[1]);
    }


    public void mouseDragged(MouseEvent e) {
    }

    // Implement MouseListener
    public void mouseEntered(MouseEvent e) {
        if (showProfile)
            setCursor(new java.awt.Cursor(java.awt.Cursor.CROSSHAIR_CURSOR));
    }

    public void mouseExited(MouseEvent e) {
        if (showProfile)
            setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }


    // Variables declaration
    private javax.swing.JLabel jLabelSelect;
    private javax.swing.JRadioButton jRadioButton0;
    private javax.swing.JRadioButton jRadioButton1;
    private javax.swing.JRadioButton jRadioButton2;
    private com.imsl.chart.JPanelChart jPanelChart;
    private javax.swing.JTextArea displayText;
    private javax.swing.JCheckBox jCheckBox;
    private javax.swing.JPanel jPanelTop;
    private javax.swing.JPanel jPanelLeft;
    private javax.swing.JPanel jPanelRight;
    // End of variables declaration
}