package edu.sc.seis.gee.task;

import javax.swing.DefaultListModel;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import edu.sc.seis.TauP.Arrival;
import edu.sc.seis.TauP.ArrivalTableModel;
import edu.sc.seis.TauP.PathPlot;
import edu.sc.seis.TauP.PhaseDialog;
import edu.sc.seis.TauP.PierceTableModel;
import edu.sc.seis.TauP.TauModelException;
import edu.sc.seis.TauP.TauP_Path;
import edu.sc.seis.TauP.TauP_Pierce;
import edu.sc.seis.TauP.TauP_Time;
import edu.sc.seis.fissuresUtil.exceptionHandler.GlobalExceptionHandler;

/*
 This is a temporary version of TauP so that it can be modified w/o
 releasing a new version of TauP


 The TauP Toolkit: Flexible Seismic Travel-Time and Raypath Utilities.
 Copyright (C) 1998-2000 University of South Carolina

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

 The current version can be found at
 <A HREF="www.seis.sc.edu">http://www.seis.sc.edu</A>

 Bug reports and comments should be directed to
 H. Philip Crotwell, crotwell@seis.sc.edu or
 Tom Owens, owens@seis.sc.edu

 */

/**
 *
 * @author H. Philip Crotwell
 * @version 1.1.3 Fri Apr  5 14:12:19 GMT 2002




 */
public class TauP extends javax.swing.JFrame {

    /** Initializes the Form */
    protected double distance = 0;

    protected javax.swing.JTable timeTable, pierceTable;

    protected ArrivalTableModel arrivalTM;
    PierceTableModel pierceTableModel;
    protected PathPlot pathPlotArea;

    public TauP() {
        this("The TauP Toolkit");
    }

    public TauP(String title){
        super(title);
        initComponents ();
        pack ();
        try {
            timeTool = new TauP_Time("iasp91");
            timeTool.init();
            pierceTool = new TauP_Pierce(timeTool.getTauModel());
            pierceTool.init();
            pathTool = new TauP_Path(timeTool.getTauModel());
            pathTool.init();
            phaseDialog = new PhaseDialog(this, false);
            phaseDialog.setPhases(timeTool.getPhaseNames());

            pathPlotArea = new PathPlot();
            pathPlotArea.setPreferredSize(new java.awt.Dimension(500, 300));
            pathPlotArea.setMinimumSize(new java.awt.Dimension(500, 200));
            pathPanel.add(pathPlotArea, java.awt.BorderLayout.CENTER);

        } catch (TauModelException e) {
            GlobalExceptionHandler.handle(e);
        } catch (java.io.IOException e) {
            GlobalExceptionHandler.handle(e);
        }

        arrivalTM = new ArrivalTableModel();
        timeTable = new javax.swing.JTable(arrivalTM);

        javax.swing.JScrollPane timeTableScrollPane =
            new javax.swing.JScrollPane (timeTable);
        timeTableScrollPane.setPreferredSize(new java.awt.Dimension(500, 300));
        timeTableScrollPane.setMinimumSize(new java.awt.Dimension(500, 200));

        timePanel.add (timeTableScrollPane, java.awt.BorderLayout.CENTER);

        modelComboBox.addItem("iasp91");
        modelComboBox.addItem("prem");
        modelComboBox.addItem("qdt");
        setSize(new java.awt.Dimension(500, 300));

        pierceTableModel = new PierceTableModel();
        pierceTable = new JTable(pierceTableModel);

        pierceArrivalList.addListSelectionListener
            (new ListSelectionListener() {
                    public void valueChanged(ListSelectionEvent e) {
                        if ( ! e.getValueIsAdjusting()) {
                            pierceListValueChanged(e);
                        }
                    }
                });
        jScrollPane2.setViewportView(pierceTable);
        pierceModel = new DefaultListModel();
        pierceArrivalList.setModel(pierceModel);

        // path list
        jList1.setModel(pierceModel);
        jList1.setSelectionModel(pierceArrivalList.getSelectionModel());
        validate();
    }

    /** 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 FormEditor.
     */
    private void initComponents () {//GEN-BEGIN:initComponents
        // This code was developed using a non-commercially licensed version of NetBeans Developer 2.x.
        // For details, see http://www.netbeans.com/non_commercial.html

        addWindowListener (new java.awt.event.WindowAdapter () {
                    public void windowClosing (java.awt.event.WindowEvent evt) {
                        exitForm (evt);
                    }
                }
                          );
        getContentPane ().setLayout (new java.awt.BorderLayout ());

        jTabbedPane1 = new javax.swing.JTabbedPane ();
        jTabbedPane1.setMinimumSize (new java.awt.Dimension(200, 200));

        timePanel = new javax.swing.JPanel ();
        timePanel.setToolTipText ("travel times");
        timePanel.setName ("Time");
        timePanel.setLayout (new java.awt.BorderLayout ());

        jTabbedPane1.addTab ("Time", null, timePanel, "travel times");

        piercePanel = new javax.swing.JPanel ();
        piercePanel.setToolTipText ("pierce points");
        piercePanel.setName ("Pierce");
        piercePanel.setLayout (new java.awt.BorderLayout ());

        jScrollPane1 = new javax.swing.JScrollPane ();

        pierceArrivalList = new javax.swing.JList ();
        pierceArrivalList.setPreferredSize (new java.awt.Dimension(60, 60));
        pierceArrivalList.setSelectionMode (javax.swing.ListSelectionModel.SINGLE_SELECTION);
        pierceArrivalList.setMinimumSize (new java.awt.Dimension(60, 60));
        jScrollPane1.add (pierceArrivalList);

        jScrollPane1.setViewportView (pierceArrivalList);
        piercePanel.add (jScrollPane1, "West");

        jScrollPane2 = new javax.swing.JScrollPane ();

        piercePanel.add (jScrollPane2, "Center");

        jTabbedPane1.addTab ("Pierce", piercePanel);

        pathPanel = new javax.swing.JPanel ();
        pathPanel.setToolTipText ("path points");
        pathPanel.setName ("Path Points");
        pathPanel.setLayout (new java.awt.BorderLayout ());

        jScrollPane3 = new javax.swing.JScrollPane ();

        jList1 = new javax.swing.JList ();
        jList1.setPreferredSize (new java.awt.Dimension(60, 60));
        jList1.setMinimumSize (new java.awt.Dimension(60, 60));

        jScrollPane3.setViewportView (jList1);
        pathPanel.add (jScrollPane3, "West");

        jTabbedPane1.addTab ("Path", pathPanel);

        getContentPane ().add (jTabbedPane1, "Center");

        jPanel1 = new javax.swing.JPanel ();
        jPanel1.setLayout (new java.awt.GridBagLayout ());
        java.awt.GridBagConstraints gridBagConstraints1;

        jLabel1 = new javax.swing.JLabel ();
        jLabel1.setText ("Model");
        jLabel1.setName ("modelLabel");
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 0;
        gridBagConstraints1.gridy = 0;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel1.add (jLabel1, gridBagConstraints1);

        modelComboBox = new javax.swing.JComboBox ();
        modelComboBox.setToolTipText ("choose a model");
        modelComboBox.setActionCommand ("modelChanged");
        modelComboBox.setName ("modelMenu");
        modelComboBox.addActionListener (new java.awt.event.ActionListener () {
                    public void actionPerformed (java.awt.event.ActionEvent evt) {
                        chooseModelActionPerformed (evt);
                    }
                }
                                        );
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 1;
        gridBagConstraints1.gridy = 0;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel1.add (modelComboBox, gridBagConstraints1);

        jLabel2 = new javax.swing.JLabel ();
        jLabel2.setText ("Distance (deg)");
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 2;
        gridBagConstraints1.gridy = 0;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints1.insets = new java.awt.Insets (0, 10, 0, 0);
        gridBagConstraints1.anchor = java.awt.GridBagConstraints.EAST;
        jPanel1.add (jLabel2, gridBagConstraints1);

        distanceTextField = new javax.swing.JTextField ();
        distanceTextField.setToolTipText ("distance in degrees");
        distanceTextField.setPreferredSize (new java.awt.Dimension(100, 21));
        distanceTextField.setMinimumSize (new java.awt.Dimension(100, 21));
        distanceTextField.setText ("50.0");
        distanceTextField.addActionListener (new java.awt.event.ActionListener () {
                    public void actionPerformed (java.awt.event.ActionEvent evt) {
                        distanceActionPerformed (evt);
                    }
                }
                                            );
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 3;
        gridBagConstraints1.gridy = 0;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel1.add (distanceTextField, gridBagConstraints1);

        jLabel3 = new javax.swing.JLabel ();
        jLabel3.setText ("Depth");
        jLabel3.setHorizontalAlignment (javax.swing.SwingConstants.RIGHT);
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 2;
        gridBagConstraints1.gridy = 1;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints1.insets = new java.awt.Insets (0, 10, 0, 0);
        gridBagConstraints1.anchor = java.awt.GridBagConstraints.EAST;
        jPanel1.add (jLabel3, gridBagConstraints1);

        depthTextField = new javax.swing.JTextField ();
        depthTextField.setToolTipText ("source depth in km");
        depthTextField.setPreferredSize (new java.awt.Dimension(100, 21));
        depthTextField.setMinimumSize (new java.awt.Dimension(100, 21));
        depthTextField.setText ("0.0");
        depthTextField.setName ("depthTextField");
        depthTextField.addActionListener (new java.awt.event.ActionListener () {
                    public void actionPerformed (java.awt.event.ActionEvent evt) {
                        depthActionPerformed (evt);
                    }
                } );

        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 3;
        gridBagConstraints1.gridy = 1;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel1.add (depthTextField, gridBagConstraints1);

        phaseChooserButton = new javax.swing.JButton ();
        phaseChooserButton.setToolTipText ("show phase chooser");
        phaseChooserButton.setText ("Phases");
        phaseChooserButton.setActionCommand ("showPhases");
        phaseChooserButton.setLabel ("Phases");
        phaseChooserButton.setName ("phaseButton");
        phaseChooserButton.addActionListener (new java.awt.event.ActionListener () {
                    public void actionPerformed (java.awt.event.ActionEvent evt) {
                        phaseChooserActionPerformed (evt);
                    }
                }
                                             );
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 1;
        gridBagConstraints1.gridy = 1;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPanel1.add (phaseChooserButton, gridBagConstraints1);

        calculateButton = new javax.swing.JButton ();
        calculateButton.setToolTipText ("calculate times");
        calculateButton.setText ("Calculate");
        calculateButton.addActionListener (new java.awt.event.ActionListener () {
                    public void actionPerformed (java.awt.event.ActionEvent evt) {
                        calculateActionPerformed (evt);
                    }
                }
                                          );
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 4;
        gridBagConstraints1.gridy = 0;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints1.insets = new java.awt.Insets (0, 20, 0, 0);
        jPanel1.add (calculateButton, gridBagConstraints1);

        jButton1 = new javax.swing.JButton ();
        jButton1.setText ("Quit");
        jButton1.setActionCommand ("quit");
        jButton1.setLabel ("Quit");
        jButton1.addActionListener (new java.awt.event.ActionListener () {
                    public void actionPerformed (java.awt.event.ActionEvent evt) {
                        quitActionPerformed (evt);
                    }
                }
                                   );
        gridBagConstraints1 = new java.awt.GridBagConstraints ();
        gridBagConstraints1.gridx = 4;
        gridBagConstraints1.gridy = 1;
        gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints1.insets = new java.awt.Insets (0, 20, 0, 0);
        jPanel1.add (jButton1, gridBagConstraints1);

        getContentPane ().add (jPanel1, "South");


    }//GEN-END:initComponents


    protected boolean quitExits = false;

    /**
     * Get the value of quitExits.
     * @return Value of quitExits.
     */
    public boolean getQuitExits() {return quitExits;}

    /**
     * Set the value of quitExits.
     * @param v  Value to assign to quitExits.
     */
    public void setQuitExits(boolean  v) {this.quitExits = v;}


    private void phaseChooserActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_phaseChooserActionPerformed
        // Add your handling code here:
        phaseDialog.setVisible(true);
    }//GEN-LAST:event_phaseChooserActionPerformed

    private void quitActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_quitActionPerformed
        // Add your handling code here:
        if (getQuitExits()) {
            System.exit(0);
        } else {
            dispose();
        }
    }//GEN-LAST:event_quitActionPerformed

    private void calculateActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_calculateActionPerformed
        // Add your handling code here:
        try {
            timeTool.setSourceDepth(Double.valueOf(depthTextField.getText()).doubleValue());
            timeTool.clearPhaseNames();
            timeTool.setPhaseNames(phaseDialog.getPhases());
            setDistance(Double.valueOf(distanceTextField.getText()).doubleValue());
            timeTool.calculate(distance);

            pierceTool.setSourceDepth(Double.valueOf(depthTextField.getText()).doubleValue());
            pierceTool.clearPhaseNames();
            pierceTool.setPhaseNames(phaseDialog.getPhases());
            pierceTool.calculate(distance);
            pathTool.setSourceDepth(Double.valueOf(depthTextField.getText()).doubleValue());
            pathTool.clearPhaseNames();
            pathTool.setPhaseNames(phaseDialog.getPhases());
            pathTool.calculate(distance);

            showResults();
        } catch (Exception e) {
            GlobalExceptionHandler.handle("exception in calculate ",e);
        }
    }//GEN-LAST:event_calculateActionPerformed

    public synchronized Arrival[] calculate(double distance, double depth, String[] phases){
        try {
            timeTool.setSourceDepth(depth);
            timeTool.clearPhaseNames();
            timeTool.setPhaseNames(phases);
            setDistance(distance);
            timeTool.calculate(distance);
            pierceTool.setSourceDepth(depth);
            pierceTool.clearPhaseNames();
            pierceTool.setPhaseNames(phases);
            pierceTool.calculate(distance);
            pathTool.setSourceDepth(depth);
            pathTool.clearPhaseNames();
            pathTool.setPhaseNames(phases);
            pathTool.calculate(distance);
        }catch (Exception e){
            GlobalExceptionHandler.handle("exception in calculate ",e);
        }
        return timeTool.getArrivals().toArray(new Arrival[0]);
    }

    public Arrival[] calculate(double distance, double depth){
        return calculate(distance, depth, phaseDialog.getPhases());
    }

    public void setPhases(String[] phases){
        phaseDialog.setPhases(phases);
    }

    public void setSelectedPhases(String[] phases){
        phaseDialog.setSelectedPhases(phases);
    }

    private void distanceActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_distanceActionPerformed
        // Add your handling code here:
        setDistance(Double.valueOf(evt.getActionCommand()).doubleValue());
        calculateActionPerformed(evt);
    }//GEN-LAST:event_distanceActionPerformed

    private void depthActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_distanceActionPerformed
        // Add your handling code here:
        setDepth(Double.valueOf(evt.getActionCommand()).doubleValue());
        calculateActionPerformed(evt);
    }//GEN-LAST:event_distanceActionPerformed

    private void chooseModelActionPerformed (java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseModelActionPerformed
        // Add your handling code here:
        setModel((String)(modelComboBox.getSelectedItem()));
    }//GEN-LAST:event_chooseModelActionPerformed

    private void pierceListValueChanged(ListSelectionEvent e) {
        pierceTableModel.setSelectedIndex(pierceArrivalList.getSelectedIndex());
        pathPlotArea.setSelectedIndex(pierceArrivalList.getSelectedIndex());
    }

    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
        if (getQuitExits()) {
            System.exit(0);
        } else {
            dispose();
        }
    }//GEN-LAST:event_exitForm


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTabbedPane jTabbedPane1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel timePanel;
    private javax.swing.JPanel piercePanel;
    private javax.swing.JPanel pathPanel;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JList pierceArrivalList;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JComboBox modelComboBox;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JTextField distanceTextField;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JTextField depthTextField;
    private javax.swing.JButton phaseChooserButton;
    private javax.swing.JButton calculateButton;
    private javax.swing.JButton jButton1;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JList jList1;
    // End of variables declaration//GEN-END:variables

    private TauP_Time timeTool;
    private TauP_Pierce pierceTool;
    private TauP_Path pathTool;
    private PhaseDialog phaseDialog;
    private DefaultListModel pierceModel;

    protected void setModel(String modelName) {
        try {
            timeTool.loadTauModel(modelName);
            pierceTool.setTauModel(timeTool.getTauModel());
            pathTool.setTauModel(timeTool.getTauModel());
        } catch (Exception e) {
            GlobalExceptionHandler.handle(e);
        }
    }

    protected void setDepth(double depth) {
        timeTool.setSourceDepth(depth);
    }

    protected void setDistance(double distance) {
        this.distance = distance;
    }

    protected void showResults() {
        arrivalTM.setArrivals(timeTool.getArrivals());
        pierceTableModel.setArrivals(pierceTool.getArrivals());
        pierceModel.removeAllElements();
        for (int i=0; i< pierceTool.getNumArrivals(); i++) {
            pierceModel.addElement(pierceTool.getArrival(i).getName());
        }
        pierceArrivalList.setSelectedIndex(0);

        pathPlotArea.setTauModel(pathTool.getTauModel());
        pathPlotArea.removeAllElements();
        for (int i=0; i< pathTool.getNumArrivals(); i++) {
            pathPlotArea.addElement(pathTool.getArrival(i));
        }
        if(taupListener != null){
            taupListener.update();
        }
        pathPlotArea.repaint();
    }

    private PhasePlotTask taupListener;

    public void setTauPListener(PhasePlotTask listener){
        taupListener = listener;
    }

    public static void main(java.lang.String[] args) {
        TauP t = new TauP();
        t.setQuitExits(true);
        t.show();
    }

}
