/*
 * -------------------------------------------------------------------------
 *      $Id: ChartPanel.java,v 1.10 2004/05/26 18:03:06 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.
 *--------------------------------------------------------------------------
 */

package com.imsl.demo.BondChart;
import com.imsl.finance.*;
import com.imsl.chart.*;
import java.awt.*;
import java.text.*;
import java.util.*;
import java.io.*;

/**
 *
 * @author  brophy
 * @created September 21, 2001
 */
public class ChartPanel extends JPanelChart {
    static final DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT,  Locale.US);
    static final NumberFormat percentFormat = new DecimalFormat("0.00'%'");

    static private DayCountBasis basis = DayCountBasis.BasisActualActual;
    static private double par = 100.;
    static private int freq = Bond.SEMIANNUAL;

    private GregorianCalendar settlement;
    private double coupon[];
    private GregorianCalendar maturity[];
    private AxisXY  axis;

    /**
     *  Table of data curves.
     *  Keys are the index number of the bond.
     *  Values are Data objects.
     *  Entries are made into this table only when a curve is needed.
     *  When the curve is removed, its paint attribute is set to false.
     */
    private Hashtable hashCurve;

    /** Creates new form ChartPanel */
    public ChartPanel(DialogSelect ds) {
        initComponents();
        Dimension ss = getToolkit().getScreenSize();
        setPreferredSize(new Dimension(ss.width/2, (int)(ss.width/2/1.25)));

        settlement = new GregorianCalendar();
        settlement.add(GregorianCalendar.DATE, 7);
        try {
            readData();
        } catch (Exception e) {
            e.printStackTrace();
        }

        chart = new Chart(this);
        chart.getChartTitle().setFontSize(20);
        chart.getBackground().setFillColor("lightYellow");

        axis = new AxisXY(chart);
        axis.getAxisX().setTextFormat(new java.text.DecimalFormat("0'%'"));

        axis.getLegend().setPaint(true);
        axis.getLegend().setViewport(0.7, 1.0, 0.1, 0.9);

        axis.getAxisX().setWindow(0.0, 20);
        axis.getAxisY().setWindow(0, 1000.0);

        chart.getChartTitle().setTitle("Sensitivity of Bond Prices");
        axis.getAxisX().getAxisTitle().setTitle("Market Rate");
        axis.getAxisY().getAxisTitle().setTitle("Bond Price");
        repaint();

        ds.setChartPanel(this);
        hashCurve = new Hashtable();
        for (int iBond = 0;  iBond < coupon.length;  iBond++) {
            ds.addBond(iBond, maturity[iBond], coupon[iBond]);
        }

        ds.pack();
        ds.show();
    }


    private void readData() throws IOException, java.text.ParseException {
        InputStream is = getClass().getResourceAsStream("TBondData.csv");
        Reader fr = new InputStreamReader(is);
        LineNumberReader lnr = new LineNumberReader(fr);

        long now = new Date().getTime();
        ArrayList listCoupon = new ArrayList();
        ArrayList listMaturity = new ArrayList();
        while (true) {
            String line = lnr.readLine();
            if (line == null)  break;
            StringTokenizer st = new StringTokenizer(line,",");
            Double coupon = Double.valueOf(st.nextToken());
            Date maturity = dateFormat.parse(st.nextToken());
            if (maturity.getTime() < now)  continue;
            listCoupon.add(coupon);
            listMaturity.add(maturity);
        }
        // first element may yeild a "maturity is not after settlement"
        // exception, so just remove it now.
        //listCoupon.remove(0);
        //listMaturity.remove(0);
        
        Iterator iterCoupon = listCoupon.iterator();
        Iterator iterMaturity = listMaturity.iterator();
        int n = listCoupon.size();
        coupon = new double[n];
        maturity = new GregorianCalendar[n];
        for (int k = 0;  k < n;  k++) {
            coupon[k] = ((Double)listCoupon.get(k)).doubleValue();
            GregorianCalendar g = new GregorianCalendar();
            g.setTime((Date)listMaturity.get(k));
            maturity[k] = g;
        }
        
    }

    private Data createLine(int iBond) {
        int n = 101;
        double x[] = new double[n];
        double y[] = new double[n];
        for (int k = 0;  k < n;  k++) {
            x[k] = 20.0*k/(n-1);
            y[k] = Bond.price(settlement, maturity[iBond], 0.01*coupon[iBond], 0.01*x[k], par, freq, basis);
        }
        Color color = nextColor();
        Data data = new Data(axis, x, y);
        data.setDataType(Data.DATA_TYPE_LINE);
        data.setLineColor(color);

        Object arg[] = new Object[2];
        arg[0] = dateFormat.format(maturity[iBond].getTime());
        arg[1] = percentFormat.format(coupon[iBond]);
        data.setTitle(arg[0]+" @ "+arg[1]);
        //new ToolTip(data);
        return data;
    }

    void showCurve(int iBond, boolean visible) {
        Integer IBond = new Integer(iBond);
        Data data = (Data)hashCurve.get(IBond);
        if (visible) {
            if (data == null) {
                data = createLine(iBond);
                hashCurve.put(IBond, data);
            }
        }
        if (data != null)  data.setPaint(visible);
        repaint();
    }


    /** 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


    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables


    static private Color colorList[] = {Color.red, Color.blue, Color.black, Color.magenta, Color.yellow, Color.cyan};
    private int nextColor = 0;

    private Color nextColor() {
        Color c = colorList[nextColor++];
        if (nextColor == colorList.length)  nextColor = 0;
        return c;
    }
}