/*
 * -------------------------------------------------------------------------
 *      $Id: Efficient.java,v 1.3 2004/05/26 18:08:33 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.Efficient;
import com.imsl.chart.*;
import com.imsl.stat.*;
import java.awt.Color;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.image.BufferedImage;

/**
 *
 * @author  Kim Ju-Yeol
 * @created October 9, 2002
 */
public class Efficient extends JFrameChart implements java.awt.event.MouseListener {
    
    private javax.swing.JPanel panel;
    private javax.swing.JLabel     xstartValue, xendValue, ystartValue, yendValue;
    private javax.swing.JLabel  jLabelLen;
    private javax.swing.JPopupMenu popup;
    private java.awt.Point saveReportLoc;
    private final java.awt.Cursor waitCursor = new java.awt.Cursor(java.awt.Cursor.WAIT_CURSOR);
    private final java.awt.Cursor defaultCursor = new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR);
    private AxisXY  axis;
    private Data  data;
    private Chart chart;
    private Computer computer;
    private InfoDialog info;
    private double[] results, expected_ret;
    
    public Efficient (boolean exitOnClose) {
        if (!exitOnClose) {
            Object l[] = getListeners(java.awt.event.WindowListener.class);
            for (int k = 0; k < l.length; k++) {
                removeWindowListener((java.awt.event.WindowListener) l[k]);
            }
        }

        com.imsl.demo.gallery.Describe des = new com.imsl.demo.gallery.Describe(this, "/com/imsl/demo/Efficient/Efficient.html");
        des.show();
        java.awt.Dimension dess = des.getSize();

        computer = new Computer();
        computer.initialize();
        
        info = new InfoDialog(this, false);
        java.awt.Dimension is = info.getSize();
        
        java.awt.Dimension ss = getToolkit().getScreenSize();
        int w = Math.min(ss.width/2, ss.height-dess.height-32);
        if (w > dess.width-is.width) {
            w = dess.width - is.width;
        }
        setSize(w, w);
        setLocation(ss.width-dess.width+is.width, dess.height);
        setTitle("Efficient Frontier");
        saveReportLoc = new java.awt.Point(ss.width-dess.width+is.width+w/4, dess.height+w/4);

        createChart();
        initComponents();
        
        // listen for mouse press events
        panel = getPanel();
        panel.addMouseListener(this);
        
        drawChart();

        info.setLocation(ss.width-dess.width, dess.height);
        info.setVisible(true);
    }
    
    private void createChart() {
        chart = getChart();
        chart.getChartTitle().setTitle("Portfolio Selection Demo");
        chart.getChartTitle().setFontSize(14);
        chart.getChartTitle().setTextColor("blue");

        axis = new AxisXY(chart);
        axis.getAxisX().getAxisTitle().setTitle("Expected Return, %");
        axis.getAxisY().getAxisTitle().setTitle("Level of Risk, %");
        axis.getAxisX().setAutoscaleInput(AxisXY.AUTOSCALE_OFF);
        axis.setViewport(0.15, 0.9, 0.1, 0.8);
    }
    
    // Save a nimage using JAI
    private void genAsJAIBitmap() {
        System.out.println("genAsJAIBitmap()");

        java.awt.Dimension sz = chart.getScreenSize();
        java.awt.Image image = chart.getComponent().createImage((int)sz.getWidth(), (int)sz.getHeight());
        chart.paintChart(image.getGraphics());
        javax.media.jai.RenderedOp im = javax.media.jai.JAI.create("AWTImage", image);
        
        String filename = getFilename();
        if (filename != "") {
            javax.media.jai.JAI.create("filestore", im,  filename, "PNG");
            java.io.File file = new java.io.File(filename);
            JOptionPane.showMessageDialog(this, "Finished Save As JAI\nFilename is " + filename, 
                "Save As Results", JOptionPane.INFORMATION_MESSAGE);
        }
    }
    
    // Save an image using ImageIO
    private void genAsImageIOBitmap() {
        System.out.println("genAsImageIOBitmap()");

        java.awt.Dimension sz = chart.getScreenSize();
        int width = (int)sz.getWidth();
        int height = (int)sz.getHeight();
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR_PRE);
        chart.paintChart(bi.getGraphics());
        String filename = getFilename();
        if (filename != "") {
            java.io.File file = new java.io.File(filename);
            try {
                javax.imageio.ImageIO.write(bi, "PNG", file);
                JOptionPane.showMessageDialog(this, "Finished Save As ImageIO\nFilename is " + filename, 
                    "Save As Results", JOptionPane.INFORMATION_MESSAGE);
            } catch (Exception e) {
                String name = e.toString().substring(0,e.toString().indexOf(':'));
                JOptionPane.showMessageDialog(this, e.getMessage(), name, JOptionPane.ERROR_MESSAGE);
                e.printStackTrace();
            }
        }
    }
    
    private String getFilename() {
        System.out.println("getFilename()");
        
        javax.swing.JFileChooser fileChooser = new javax.swing.JFileChooser();
        //fileChooser.setDialogType(javax.swing.JFileChooser.SAVE_DIALOG);
        fileChooser.setApproveButtonText("Save");
        fileChooser.setApproveButtonToolTipText("Save with this file name");
        fileChooser.setDialogTitle("Save As");
        fileChooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_AND_DIRECTORIES);
        fileChooser.setCurrentDirectory(new java.io.File("."));

        int result = fileChooser.showOpenDialog(this);
        if (result == javax.swing.JFileChooser.CANCEL_OPTION) return "";

        java.io.File file = fileChooser.getSelectedFile();
        String fileName = file.getPath();
        if (fileName == null || fileName.equals("")) {
            JOptionPane.showMessageDialog(this,"Invalid File Name","Invalid File Name",JOptionPane.ERROR_MESSAGE);
            return "";
        } else {
            return fileName;
        }
    }   
    
    public Computer getComputer() {
        return computer;
    }
    
    // Update
    public void redrawChart() {
        axis.setAutoscaleInput(ChartNode.AUTOSCALE_DATA);
        data.remove();
        drawChart();
    }
    
    // Draw Chart
    private void drawChart() {
        results = Computer.getResults();
        expected_ret = Computer.getExpected_ret();
        
        String model_type;
        switch (computer.getModel()) {
            case 0: model_type = "EWMA";
                break;
            case 1: model_type = "SMA";
                break;
            case 2: model_type = "AHP";
                break;
            default: model_type = "EWMA";
        }
        
        Summary summary_x = new Summary();
        summary_x.update(expected_ret);
        double xa = summary_x.getMinimum();
        double xb = summary_x.getMaximum();
        
        Summary summary_y = new Summary();
        summary_y.update(results);
        double ya = summary_y.getMinimum();
        double yb = summary_y.getMaximum();
        
        data = new Data(axis, expected_ret, results);
        data.setDataType(Data.DATA_TYPE_LINE);
        data.setLineColor("red");
        
        axis.getAxisX().setWindow(xa, xb);
        repaint();
        
        // update the info box
        final java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
        nf.setMaximumFractionDigits(2);
        nf.setGroupingUsed(false);
        
        xstartValue.setText("[" + nf.format(xa));
        ystartValue.setText("[" + nf.format(ya));
        
        xendValue.setText(", " + nf.format(xb) + "]");
        yendValue.setText(", " + nf.format(yb) + "]");
        
        String length_data = Long.toString(results.length);
        
        StringBuffer sb = new StringBuffer(2048);
        sb.append("<html><body><font face='arial' size=4>");
        sb.append("<p align='center'><b>");
        sb.append("Statistical Model is " + model_type);
        sb.append("</b></p>");
        
        sb.append("<p align='center'><font face='arial' size=3><b>");
        sb.append("<center>Trial # : " + length_data + "</center>");
        sb.append("</b></p>");
        
        sb.append("<p align='center'><font face='arial' size=3><b>");
        sb.append("<center>Input Parameters</center>");
        sb.append("</b>");
        
        sb.append("<p align='center'>");
        sb.append("<table border=1 width=300>");
        
        appendLine(sb);
        appendText(sb, "Commodity");
        appendText(sb, "RETURN");
        appendText(sb, "RISK");
        closeLine(sb);
        
        String[] com = Computer.getCommodity();
        double[] ret = Computer.getReturn();
        double[] risk = Computer.getRisk();
        final java.text.DecimalFormat df = new java.text.DecimalFormat("##0.00");
        
        for (int i=0; i<com.length; i++) {
            appendLine(sb);
            appendText(sb, com[i]);
            appendRow(sb, df.format(ret[i]));
            appendRow(sb, df.format(risk[i]));
            closeLine(sb);
        }
        
        sb.append("</table></body></html>");
        info.setText(sb.toString());
        info.repaint();
    }
    
    private void appendLine(StringBuffer sb) {
        sb.append("<tr width=100>");
    }
    
    private void closeLine(StringBuffer sb) {
        sb.append("</tr>");
    }
    
    private void appendText(StringBuffer sb, String title) {
        sb.append("<td align='center'><font face='arial' size=3><b>");
        sb.append(title);
        sb.append("</td>");
    }
    
    private void appendRow(StringBuffer sb, String value) {
        sb.append("<td align='center'><font face='arial' size=3>");
        sb.append(value);
        sb.append("</td>");
    }
    
    // Coordinate  & Plot Information displays
    private void initComponents() {
        javax.swing.JPanel panelControl = new javax.swing.JPanel();
        panelControl.setBackground(Color.white);
        panelControl.setLayout(new java.awt.GridLayout(2,1));
        
        javax.swing.JPanel panelInfo = new javax.swing.JPanel(new java.awt.FlowLayout(java.awt.FlowLayout.LEADING));
        panelInfo.setBackground(Color.white);
        
        JLabel jLabelInfo = new JLabel("Data Source:  ",JLabel.LEADING);
        JLabel jLabelLen = new JLabel("LG Insuarance Co. in Korea",JLabel.LEADING);
        jLabelInfo.setForeground(Color.blue);
        jLabelLen.setForeground(Color.blue);
        
        panelInfo.add(jLabelInfo);
        panelInfo.add(jLabelLen);
        
        javax.swing.JPanel panelXYvalue = new javax.swing.JPanel(new java.awt.FlowLayout(java.awt.FlowLayout.LEADING));
        panelXYvalue.setBackground(Color.white);
        
        JLabel title = new JLabel("Data Value for Region  -  ", JLabel.LEADING);
        JLabel xLabel = new JLabel(" X Range = ", JLabel.LEADING);
        xstartValue = new JLabel("", JLabel.TRAILING);
        xendValue = new JLabel("", JLabel.TRAILING);
        JLabel yLabel = new JLabel("   Y Range = ", JLabel.LEADING);
        ystartValue = new JLabel("", JLabel.TRAILING);
        yendValue = new JLabel("", JLabel.TRAILING);
        
        panelXYvalue.add(title);
        panelXYvalue.add(xLabel);
        panelXYvalue.add(xstartValue);
        panelXYvalue.add(xendValue);
        panelXYvalue.add(yLabel);
        panelXYvalue.add(ystartValue);
        panelXYvalue.add(yendValue);
        
        panelControl.add(panelInfo);
        panelControl.add(panelXYvalue);
        
        getContentPane().add(panelControl, java.awt.BorderLayout.SOUTH);
        
        // Add Pop Menu for Save Image in JFrameChart
        popup = new javax.swing.JPopupMenu();
        
        javax.swing.JMenuItem jaimenu = new javax.swing.JMenuItem();
        jaimenu.setText("Save as Image Using JAI");
        jaimenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                popup.setVisible(false);
                setCursor(waitCursor);
                genAsJAIBitmap();
                setCursor(defaultCursor);
            }
        });
        
        javax.swing.JMenuItem imageIOmenu = new javax.swing.JMenuItem();
        imageIOmenu.setText("Save as Image Using ImageIO");
        imageIOmenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                popup.setVisible(false);
                setCursor(waitCursor);
                genAsImageIOBitmap();
                setCursor(defaultCursor);
            }
        });
        
        javax.swing.JMenuItem dataMenu = new javax.swing.JMenuItem();
        dataMenu.setText("Save Data as Text");
        dataMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent e) {
                popup.setVisible(false);
                String fileName = getFilename();
                if (fileName != "") {
                    setCursor(waitCursor);
                    computer.saveData(panel, fileName);
                    setCursor(defaultCursor);
                }
            }
        });
        
        popup.add(jaimenu);
        popup.add(imageIOmenu);
        popup.add(dataMenu);
        popup.setOpaque(true);
        popup.setLightWeightPopupEnabled(true);        
    }

    public void mousePressed(java.awt.event.MouseEvent mouseEvent) {
        if (mouseEvent.getButton() != 1) {
            popup.show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
        }
    }
    
    public void mouseClicked(java.awt.event.MouseEvent mouseEvent) {
    }
    
    public void mouseEntered(java.awt.event.MouseEvent mouseEvent) {
    }
    
    public void mouseExited(java.awt.event.MouseEvent mouseEvent) {
    }
    
    public void mouseReleased(java.awt.event.MouseEvent mouseEvent) {
    }

    public static void main(String args[]) {
        boolean exitOnClose = true;
        if (args.length > 0 && args[0].equals("-noexit")) {
            exitOnClose = false;
        }
        new Efficient(exitOnClose).show();
    }
}