/*
 * ChartPanel.java
 *
 * Created on September 19, 2001, 4:29 PM
 */

package com.imsl.demo.StockChart;
import com.imsl.chart.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.util.Date;
import javax.swing.*;

/**
 *
 * @author  brophy
 */
public class ChartPanel extends JPanelChart
        implements MouseListener, MouseMotionListener {
    
    private AxisXY  axisPrice;
    private Data    dataMovingAverage;
    private double  time[];
    private double  high[];
    private double  low[];
    private double  close[];
    private double  vol[];
    private double  ave[];
    
    private Slice   slice = new Slice();
    private SliceDialog sliceDialog;

    /** Creates new form ChartPanel */
    public ChartPanel() {
        initComponents();
        
        sliceDialog = new SliceDialog();
        sliceDialog.setVisible(false);
        sliceDialog.setLocation(500,200);
        
        chart = new Chart(this);
        chart.getChartTitle().setTitle("Random Industries.com");
        chart.getChartTitle().setFont(new Font("Serif", Font.ITALIC|Font.BOLD, 20));
        chart.getChartTitle().setTextColor(new Color(0,128,64));
        chart.setMarkerColor(Color.red);
        chart.setTextColor(Color.blue);
     
        Date date = new Date(933051600000L); // June 27, 1999
        setData(date);
        
        // price axis
        axisPrice = new AxisXY(chart);
        axisPrice.setViewport(0.15, 0.9, 0.1, 0.65);
        axisPrice.setMarkerSize(0.5);
        HighLowClose hilo = new HighLowClose(axisPrice, date, high, low, close);
        axisPrice.getAxisX().getAxisLabel().setPaint(false);
        initGrid(axisPrice.getAxisX());
        initGrid(axisPrice.getAxisY());
        
        // moving average
        dataMovingAverage = new Data(axisPrice, time, ave);
        dataMovingAverage.setDataType(Data.DATA_TYPE_LINE);
        dataMovingAverage.setLineColor(Color.magenta);        
        
        // volume axis
        AxisXY axis = new AxisXY(chart);
        axis.setViewport(0.15, 0.9, 0.7, 0.9);
        Data data = new Data(axis, time, vol);
        data.setDataType(Data.DATA_TYPE_FILL);
        data.setFillColor(Color.orange);
        data.setFillOutlineType(Data.FILL_TYPE_NONE);
        initGrid(axis.getAxisX());
        initGrid(axis.getAxisY());
        
        axis.getAxisY().getAxisTitle().setTitle("Volume (millions)");
        axis.getAxisX().getAxisLabel().setTextAngle(270);
        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
        axis.getAxisX().getAxisLabel().setTextFormat(df);
        
        addMouseListener(this);
    }
    
    private void initGrid(Axis1D axis1d) {
        Grid grid = axis1d.getGrid();
        grid.setLineColor(Color.lightGray);
        grid.setPaint(true);
    }
    
    protected void setData(Date date) {
        int n = 300;
        high = new double[n];
        low = new double[n];
        close = new double[n];
        vol = new double[n];
        time = new double[n];
        ave = new double[n];
        high[0] = 101.;
        low[0] = 99.;
        close[0] = 100;
        vol[0] = 20.*Math.random();
        time[0] = date.getTime();
        ave[0] = close[0];
        for (int k = 1;  k < n;  k++) {
            close[k] = close[k-1] + 2.*Math.random() - 1.;
            high[k] = close[k] + 0.5*Math.random();
            low[k] = close[k] - 0.5*Math.random();
            vol[k] = 20*Math.random();
            time[k] = time[k-1] + 1000.*24.*60.*60.;
            ave[k] = 0.90*ave[k-1] + 0.1*close[k];
        }
    }
    
    public void setViewMovingAverage(boolean viewMovingAverage) {
        dataMovingAverage.setPaint(viewMovingAverage);
        repaint();
    }
    
    public Dimension getPreferredSize() {
        return new Dimension(500, 600);
    }
    
    public void paint(Graphics g) {
        super.paint(g);
        if (sliceDialog != null)  sliceDialog.paint(g);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        
        setLayout(new java.awt.BorderLayout());
        
    }//GEN-END:initComponents

    public void mouseExited(java.awt.event.MouseEvent mouseEvent) {
    }    

    public void mouseReleased(java.awt.event.MouseEvent mouseEvent) {
        removeMouseMotionListener(this);
        slice.erase();
        sliceDialog.setVisible(false);
    }    

    public void mousePressed(java.awt.event.MouseEvent mouseEvent) {
        addMouseMotionListener(this);
        double w[] = axisPrice.getAxisY().getWindow();
        int y[] = new int[2];
        axisPrice.mapUserToDevice(time[0], w[0], y);
        int y0 = y[1];
        axisPrice.mapUserToDevice(time[0], w[1], y);
        slice.setY(y0, y[1]);
        sliceDialog.setVisible(true);
    }
    
    public void mouseClicked(java.awt.event.MouseEvent mouseEvent) {
    }
    
    public void mouseEntered(java.awt.event.MouseEvent mouseEvent) {
    }
    
    public void mouseDragged(java.awt.event.MouseEvent mouseEvent) {
        slice.erase();
        double point[] = new double[2];
        axisPrice.mapDeviceToUser(mouseEvent.getX(), mouseEvent.getY(), point);
        int msday = 24*3600*1000;
        for (int k = 0;  k < time.length;  k++) {
            if (Math.abs(time[k]-point[0]) < msday) {
                slice.draw(mouseEvent.getX());
                sliceDialog.setIndex(k);
                return;
            }
        }
    }
    
    public void mouseMoved(java.awt.event.MouseEvent mouseEvent) {
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

    /**
     *  Draw a vertical line to represent the current data slice.
     */
    private class Slice {
        private int xDevice = -1;  // if < 0 then no line is drawn
        private int yDevice[] = new int[2];
        
        /**
         *  Set vertical range of the line, in device cooordinates.
         */
        void setY(int y0, int y1) {
            yDevice[0] = y0;
            yDevice[1] = y1;
        }
        
        /**
         *  Erase the data slice line, if any.
         */
        void erase() {
            if (xDevice >= 0) {
                paint();
                xDevice = -1;
            }
        }
        
        /**
         *  Draw the data slice line at a given location.
         *  @param xDevice is the x-coordinate, in device units,
         *                  at which the line is to be drawn.
         */
        void draw(int xDevice) {
            this.xDevice = xDevice;
            paint();
        }
        
        /**
         *  Actually paint the data slice line.
         */
        private void paint() {
            Graphics g = getGraphics();
            g.setXORMode(Color.white);
            g.drawLine(xDevice, yDevice[0], xDevice, yDevice[1]);
        }
    }
    
    /**
     *  Dialog box to show the value of the current slice.
     */
    private class SliceDialog extends JDialog {
        /*
         *  The body of the dialog is formatted using HTML.
         */
        final private DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT);
        final private NumberFormat vf = NumberFormat.getNumberInstance();
        final private DecimalFormat df = new DecimalFormat("0.00");
        final private MessageFormat mf = new MessageFormat(
            "<html><body bgcolor=\"yellow\"><table>" +
            "<tr><td align=\"right\"><i><font color=\"blue\">Date</td><td>{0}</td></tr>" +
            "<tr><td align=\"right\"><i><font color=\"blue\">Low</td><td >{1}</td></tr>" +
            "<tr><td align=\"right\"><i><font color=\"blue\">High</td><td >{2}</td></tr>" +
            "<tr><td align=\"right\"><i><font color=\"blue\">Close</td><td >{3}</td></tr>" +
            "<tr><td align=\"right\"><i><font color=\"blue\">Volume</td><td >{4}</td></tr>" +
            "</table></body></html>"
            );
        
        private JEditorPane   text;
        
        SliceDialog() {
            setBackground(Color.yellow);
            text = new JEditorPane();
            text.setContentType("text/html");
            text.setEditable(false);
            getContentPane().add(text);
        }
        
        public Dimension getPreferredSize() {
            return new Dimension(150,175);
        }

        void setIndex(int index) {
            String arg[] = new String[5];
            arg[0] = dateFormat.format(new Date((long)time[index]));
            arg[1] = df.format(low[index]);
            arg[2] = df.format(high[index]);
            arg[3] = df.format(close[index]);
            arg[4] = vf.format((int)(1e6*vol[index]));
            text.setText(mf.format(arg));
            pack();
        }
    }
}