import rock.*;
import org.omg.CosNaming.*;
import org.omg.CORBA.*;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.*;
import javax.swing.text.*;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;

import java.text.*;

/**
 * Creates a popup dialog box to allow specification of T, P or H, P or S, P or T, V constraints on the system evolution path.
 * @version 1.0 (August 2007)
 * @author Mark S. Ghiorso, OFM-Research Inc.
 */
public class TPHandler implements ActionListener {
  /** Initial temperature (K). */
  public double tStartVal;
  /** Final temperature (K). */
  public double tStopVal;
  /** Temperature increment (K). */
  public double tIncVal;
  /** Initial pressure (bars). */
  public double pStartVal;
  /** Final pressure (bars). */
  public double pStopVal;
  /** Pressure increment (bars). */
  public double pIncVal;
  /** Pressure-temperature gradient (bars/K). */
  public double dpdtVal;
  /** Initial enthalpy (J). */
  public double hStartVal;
  /** Final enthalpy (J). */
  public double hStopVal;
  /** Enthalpy increment (J). */
  public double hIncVal;
  /** Pressure-enthalpy gradient (bars/J). */
  public double dpdhVal;
  /** Initial entropy (J/K). */
  public double sStartVal;
  /** Final entropy (J/K). */
  public double sStopVal;
  /** Entropy increment (J/K). */
  public double sIncVal;
  /** Pressure-entropy gradient (bars-K/J). */
  public double dpdsVal;
  /** Initial volume (J/bar). */
  public double vStartVal;
  /** Final volume (J/bar). */
  public double vStopVal;
  /** Volume increment (J/bar). */
  public double vIncVal;
  /** Temperature-volume gradient (K-bar/J). */
  public double dtdvVal;

  /** Text Field boxes to hold equivalent *Val entries. */
  public JFormattedTextField tStartFTF, tStopFTF, tIncFTF, pStartFTF, pStopFTF, pIncFTF, dpdtFTF, hStartFTF, hStopFTF, 
                             hIncFTF, dpdhFTF, sStartFTF, sStopFTF, sIncFTF, dpdsFTF, vStartFTF, vStopFTF, vIncFTF, dtdvFTF;
  private NumberFormat tFormat, pFormat, hFormat, sFormat, vFormat, dpdtFormat, dpdhFormat, dpdsFormat, dtdvFormat;
  private JFrame frame;
  private rock.dRock rockRef;
  
  /**
   * Creates the GUI and initializes the class.
   * @param rockRef Instance of server-side rock object.
   */
  public TPHandler(rock.dRock rockRef) {
    this.rockRef = rockRef;
  
    Border etchedBdr1 = BorderFactory.createEtchedBorder();
    tFormat    = NumberFormat.getNumberInstance();    tFormat.setMaximumFractionDigits(1);
    pFormat    = NumberFormat.getNumberInstance();    pFormat.setMaximumFractionDigits(4);
    hFormat    = NumberFormat.getNumberInstance();    hFormat.setMaximumFractionDigits(3);
    sFormat    = NumberFormat.getNumberInstance();    sFormat.setMaximumFractionDigits(3);
    vFormat    = NumberFormat.getNumberInstance();    vFormat.setMaximumFractionDigits(3);
    dpdtFormat = NumberFormat.getNumberInstance(); dpdtFormat.setMaximumFractionDigits(6);
    dpdhFormat = NumberFormat.getNumberInstance(); dpdhFormat.setMaximumFractionDigits(6);
    dpdsFormat = NumberFormat.getNumberInstance(); dpdsFormat.setMaximumFractionDigits(6);
    dtdvFormat = NumberFormat.getNumberInstance(); dtdvFormat.setMaximumFractionDigits(6);
    
    TextHandler handler0 = new TextHandler();
    
    frame = new JFrame("Temperature, Pressure, Enthalpy, Entropy and Volume");
    frame.addWindowListener(new java.awt.event.WindowAdapter() {
        public void windowClosing(java.awt.event.WindowEvent e) {
          Frame f = (Frame) e.getSource();
    	  f.setVisible(false);
        }
      });
    Container cp1 = frame.getContentPane();
  
    GridBagLayout gbl = new GridBagLayout(); cp1.setLayout(gbl);
    
    JPanel jp1a = new JPanel(); 
	   jp1a.add(new JLabel("Temperature (C):"));
    addComponent(cp1, jp1a, 0, 0, 1, 1, GridBagConstraints.BOTH);
    
    JPanel jp1b = new JPanel(); 
	   jp1b.add(new JLabel("Pressure (GPa):"));
    addComponent(cp1, jp1b, 1, 0, 1, 1, GridBagConstraints.BOTH);

    JPanel jp1c = new JPanel(); 
	   jp1c.add(new JLabel("Enthalpy(kJ):"));
    addComponent(cp1, jp1c, 2, 0, 1, 1, GridBagConstraints.BOTH);
    
    JPanel jp1d = new JPanel(); 
	   jp1d.add(new JLabel("Entropy (J/K):"));
    addComponent(cp1, jp1d, 3, 0, 1, 1, GridBagConstraints.BOTH);

    JPanel jp1e = new JPanel(); 
	   jp1e.add(new JLabel("Volume (cc):"));
    addComponent(cp1, jp1e, 4, 0, 1, 1, GridBagConstraints.BOTH);
    
    JPanel jp2 = new JPanel(); 
	   jp2.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 
           jp2.setLayout(new GridLayout(0, 2));
    
      jp2.add(new JLabel("Start:")); 
      tStartFTF = new JFormattedTextField(tFormat); tStartFTF.setColumns(6); tStartFTF.addPropertyChangeListener(handler0);
      jp2.add(tStartFTF);
      
      jp2.add(new JLabel("Stop:"));
      tStopFTF = new JFormattedTextField(tFormat); tStopFTF.setColumns(6); tStopFTF.addPropertyChangeListener(handler0);
      jp2.add(tStopFTF);
      
      jp2.add(new JLabel("Inc:"));
      tIncFTF = new JFormattedTextField(tFormat); tIncFTF.setColumns(6); tIncFTF.addPropertyChangeListener(handler0);
      jp2.add(tIncFTF);
    
    addComponent(cp1, jp2, 0, 1, 1, 1, GridBagConstraints.BOTH);
    
    JPanel jp3 = new JPanel(); 
	   jp3.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 
           jp3.setLayout(new GridLayout(0, 2));
    
      jp3.add(new JLabel("Start:")); 
      pStartFTF = new JFormattedTextField(pFormat); pStartFTF.setColumns(7); pStartFTF.addPropertyChangeListener(handler0);
      jp3.add(pStartFTF);
      
      jp3.add(new JLabel("Stop:"));
      pStopFTF = new JFormattedTextField(pFormat); pStopFTF.setColumns(7); pStopFTF.addPropertyChangeListener(handler0);
      jp3.add(pStopFTF);
      
      jp3.add(new JLabel("Inc:"));  
      pIncFTF = new JFormattedTextField(pFormat); pIncFTF.setColumns(7); pIncFTF.addPropertyChangeListener(handler0);
      jp3.add(pIncFTF);
      
      jp3.add(new JLabel("dP/dT:")); 
      dpdtFTF = new JFormattedTextField(dpdtFormat); dpdtFTF.setColumns(7); dpdtFTF.addPropertyChangeListener(handler0);
      jp3.add(dpdtFTF);
    
    addComponent(cp1, jp3, 1, 1, 1, 1, GridBagConstraints.BOTH);

    JPanel jp4 = new JPanel(); 
	   jp4.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 
           jp4.setLayout(new GridLayout(0, 2));
    
      jp4.add(new JLabel("Start:"));	     
      hStartFTF= new JFormattedTextField(hFormat); hStartFTF.setColumns(7); hStartFTF.addPropertyChangeListener(handler0);
      jp4.add(hStartFTF);
      			  
      jp4.add(new JLabel("Stop:"));
      hStopFTF = new JFormattedTextField(hFormat); hStopFTF.setColumns(7); hStopFTF.addPropertyChangeListener(handler0); 
      jp4.add(hStopFTF);
      		  
      jp4.add(new JLabel("Inc:"));  
      hIncFTF = new JFormattedTextField(hFormat); hIncFTF.setColumns(7); hIncFTF.addPropertyChangeListener(handler0); 
      jp4.add(hIncFTF);
      
      jp4.add(new JLabel("dP/dH:"));
      dpdhFTF = new JFormattedTextField(dpdhFormat); dpdhFTF.setColumns(7); dpdhFTF.addPropertyChangeListener(handler0); 
      jp4.add(dpdhFTF);
    
    addComponent(cp1, jp4, 2, 1, 1, 1, GridBagConstraints.BOTH);
    
    JPanel jp5 = new JPanel(); 
	   jp5.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 
           jp5.setLayout(new GridLayout(0, 2));
    
      jp5.add(new JLabel("Start:")); 
      sStartFTF = new JFormattedTextField(sFormat); sStartFTF.setColumns(7); sStartFTF.addPropertyChangeListener(handler0);
      jp5.add(sStartFTF);
      
      jp5.add(new JLabel("Stop:")); 
      sStopFTF = new JFormattedTextField(sFormat); sStopFTF.setColumns(7); sStopFTF.addPropertyChangeListener(handler0); 
      jp5.add(sStopFTF);
      
      jp5.add(new JLabel("Inc:"));  
      sIncFTF = new JFormattedTextField(sFormat); sIncFTF.setColumns(7); sIncFTF.addPropertyChangeListener(handler0); 
      jp5.add(sIncFTF);
      
      jp5.add(new JLabel("dP/dS:")); 
      dpdsFTF = new JFormattedTextField(dpdsFormat); dpdsFTF.setColumns(7); dpdsFTF.addPropertyChangeListener(handler0); 
      jp5.add(dpdsFTF);
    
    addComponent(cp1, jp5, 3, 1, 1, 1, GridBagConstraints.BOTH);
    
    JPanel jp6 = new JPanel(); 
	   jp6.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 
           jp6.setLayout(new GridLayout(0, 2));
    
      jp6.add(new JLabel("Start:")); 
      vStartFTF = new JFormattedTextField(vFormat); vStartFTF.setColumns(7); vStartFTF.addPropertyChangeListener(handler0);
      jp6.add(vStartFTF);
      
      jp6.add(new JLabel("Stop:")); 
      vStopFTF = new JFormattedTextField(vFormat); vStopFTF.setColumns(7); vStopFTF.addPropertyChangeListener(handler0);
      jp6.add(vStopFTF);
      
      jp6.add(new JLabel("Inc:"));  
      vIncFTF = new JFormattedTextField(vFormat); vIncFTF.setColumns(7); vIncFTF.addPropertyChangeListener(handler0);
      jp6.add(vIncFTF);
      
      jp6.add(new JLabel("dT/dV:")); 
      dtdvFTF = new JFormattedTextField(dtdvFormat); dtdvFTF.setColumns(7); dtdvFTF.addPropertyChangeListener(handler0);
      jp6.add(dtdvFTF);
    
    addComponent(cp1, jp6, 4, 1, 1, 1, GridBagConstraints.BOTH);
    
    JPanel jp7 = new JPanel(); 
	   jp7.setBorder(etchedBdr1); 
           jp7.setLayout(new GridLayout(0, 2));
    
    JPanel jp7a = new JPanel(); 
    JButton tb1 = new JButton("Done");
	    tb1.addActionListener(new DoneHandler());
    jp7a.add(tb1); 
    jp7.add(jp7a);
    
    JPanel jp7b = new JPanel(); 
    JButton tb2 = new JButton("Compute"); 
	    tb2.addActionListener(new ComputeHandler());
    jp7b.add(tb2); 
    jp7.add(jp7b);
	  
    addComponent(cp1, jp7, 0, 2, 5, 1, GridBagConstraints.BOTH);
    
    tStartVal = 1200.0;   pStartVal =  0.1;   hStartVal = 0.0;   sStartVal = 0.0;   vStartVal = 0.0;  
    tStopVal  = 1200.0;   pStopVal  =  0.1;   hStopVal  = 0.0;   sStopVal  = 0.0;   vStopVal  = 0.0;   
    tIncVal   =    5.0;   pIncVal   =  0.0;   hIncVal	= 0.0;   sIncVal   = 0.0;   vIncVal   = 0.0;   
                          dpdtVal   =  0.0;   dpdhVal	= 0.0;   dpdsVal   = 0.0;   dtdvVal   = 0.0;
			  
    tStartFTF.setValue(new Double(tStartVal)); tStartFTF.setEditable(true);
     tStopFTF.setValue(new Double(tStopVal));   tStopFTF.setEditable(true);
      tIncFTF.setValue(new Double(tIncVal));     tIncFTF.setEditable(true);

    pStartFTF.setValue(new Double(pStartVal)); pStartFTF.setEditable(true);
     pStopFTF.setValue(new Double(pStopVal));   pStopFTF.setEditable(true);
      pIncFTF.setValue(new Double(pIncVal));     pIncFTF.setEditable(true);
      dpdtFTF.setValue(new Double(dpdtVal));     dpdtFTF.setEditable(true);

    hStartFTF.setValue(new Double(hStartVal)); hStartFTF.setEditable(false);
     hStopFTF.setValue(new Double(hStopVal));   hStopFTF.setEditable(false);
      hIncFTF.setValue(new Double(hIncVal));     hIncFTF.setEditable(false);
      dpdhFTF.setValue(new Double(dpdhVal));     dpdhFTF.setEditable(false);

    sStartFTF.setValue(new Double(sStartVal)); sStartFTF.setEditable(false);
     sStopFTF.setValue(new Double(sStopVal));   sStopFTF.setEditable(false);
      sIncFTF.setValue(new Double(sIncVal));     sIncFTF.setEditable(false);
      dpdsFTF.setValue(new Double(dpdsVal));     dpdsFTF.setEditable(false);

    vStartFTF.setValue(new Double(vStartVal)); vStartFTF.setEditable(false);
     vStopFTF.setValue(new Double(vStopVal));   vStopFTF.setEditable(false);
      vIncFTF.setValue(new Double(vIncVal));     vIncFTF.setEditable(false);
      dtdvFTF.setValue(new Double(dtdvVal));     dtdvFTF.setEditable(false);
      
    tStartFTF.setHorizontalAlignment(JTextField.RIGHT);
     tStopFTF.setHorizontalAlignment(JTextField.RIGHT);
      tIncFTF.setHorizontalAlignment(JTextField.RIGHT);
    	       
    pStartFTF.setHorizontalAlignment(JTextField.RIGHT);
     pStopFTF.setHorizontalAlignment(JTextField.RIGHT);
      pIncFTF.setHorizontalAlignment(JTextField.RIGHT);
      dpdtFTF.setHorizontalAlignment(JTextField.RIGHT);
    	       
    hStartFTF.setHorizontalAlignment(JTextField.RIGHT);
     hStopFTF.setHorizontalAlignment(JTextField.RIGHT);
      hIncFTF.setHorizontalAlignment(JTextField.RIGHT);
      dpdhFTF.setHorizontalAlignment(JTextField.RIGHT);
    	       
    sStartFTF.setHorizontalAlignment(JTextField.RIGHT);
     sStopFTF.setHorizontalAlignment(JTextField.RIGHT);
      sIncFTF.setHorizontalAlignment(JTextField.RIGHT);
      dpdsFTF.setHorizontalAlignment(JTextField.RIGHT);
    	       
    vStartFTF.setHorizontalAlignment(JTextField.RIGHT);
     vStopFTF.setHorizontalAlignment(JTextField.RIGHT);
      vIncFTF.setHorizontalAlignment(JTextField.RIGHT);
      dtdvFTF.setHorizontalAlignment(JTextField.RIGHT);
    
    frame.pack();
    frame.setLocation(100, 100);
    
  }

  /**
   * Displays the popup dialog box and populates text entries. 
   * @param e Action event that triggered the display request.
   */
  public void actionPerformed(ActionEvent e) {
    try {
      double curT = (rockRef != null) ? rockRef.getTk() - 273.15 : 1200.0;    // C
      double curP = (rockRef != null) ? rockRef.getPa()/1.0e9	 :    0.1;    // GPa
      double curH = (rockRef != null) ? (rockRef.getLiquidEnthalpy() + rockRef.getSolidEnthalpyTotal())/1000.0 : 0.0;
      double curS = (rockRef != null) ?  rockRef.getLiquidEntropy()  + rockRef.getSolidEntropyTotal()	       : 0.0;
      double curV = (rockRef != null) ? (rockRef.getLiquidVolume()   + rockRef.getSolidVolumeTotal())*1.0e6    : 0.0;
  
      // TODO -Initialize the entries and  hStartFTF.setEditable(false); getIsenthalpic, etc.
      if (tStartVal != curT) tStartVal = curT;
      if (pStartVal != curP) pStartVal = curP;
      if (hStartVal != curH) hStartVal = curH;  if (hStopVal != curH) hStopVal = curH;
      if (sStartVal != curS) sStartVal = curS;  if (sStopVal != curS) sStopVal = curS;
      if (vStartVal != curV) vStartVal = curV;  if (vStopVal != curV) vStopVal = curV;
      
      tStartFTF.setValue(new Double(tStartVal)); tStartFTF.setEditable(true);
       tStopFTF.setValue(new Double(tStopVal));   tStopFTF.setEditable(true);
        tIncFTF.setValue(new Double(tIncVal));     tIncFTF.setEditable(true);

      pStartFTF.setValue(new Double(pStartVal)); pStartFTF.setEditable(true);
       pStopFTF.setValue(new Double(pStopVal));   pStopFTF.setEditable(true);
        pIncFTF.setValue(new Double(pIncVal));     pIncFTF.setEditable(true);
        dpdtFTF.setValue(new Double(dpdtVal));     dpdtFTF.setEditable(true);

      hStartFTF.setValue(new Double(hStartVal)); hStartFTF.setEditable(false);
       hStopFTF.setValue(new Double(hStopVal));   hStopFTF.setEditable(false);
        hIncFTF.setValue(new Double(hIncVal));     hIncFTF.setEditable(false);
        dpdhFTF.setValue(new Double(dpdhVal));     dpdhFTF.setEditable(false);

      sStartFTF.setValue(new Double(sStartVal)); sStartFTF.setEditable(false);
       sStopFTF.setValue(new Double(sStopVal));   sStopFTF.setEditable(false);
        sIncFTF.setValue(new Double(sIncVal));     sIncFTF.setEditable(false);
        dpdsFTF.setValue(new Double(dpdsVal));     dpdsFTF.setEditable(false);

      vStartFTF.setValue(new Double(vStartVal)); vStartFTF.setEditable(false);
       vStopFTF.setValue(new Double(vStopVal));   vStopFTF.setEditable(false);
        vIncFTF.setValue(new Double(vIncVal));     vIncFTF.setEditable(false);
        dtdvFTF.setValue(new Double(dtdvVal));     dtdvFTF.setEditable(false);
        
      if (Melts.isenthalpic) { 
        tStartFTF.setEditable(false);  hStartFTF.setEditable(true);
         tStopFTF.setEditable(false);	hStopFTF.setEditable(true);
          tIncFTF.setEditable(false);	 hIncFTF.setEditable(true);
    	  dpdtFTF.setEditable(false);	 dpdhFTF.setEditable(true);
      } else if (Melts.isentropic) {
        tStartFTF.setEditable(false);  sStartFTF.setEditable(true);
         tStopFTF.setEditable(false);	sStopFTF.setEditable(true);
          tIncFTF.setEditable(false);	 sIncFTF.setEditable(true);
    	  dpdtFTF.setEditable(false);	 dpdsFTF.setEditable(true);
      } else if (Melts.isochoric) {
        pStartFTF.setEditable(false);  vStartFTF.setEditable(true);
         pStopFTF.setEditable(false);	vStopFTF.setEditable(true);
          pIncFTF.setEditable(false);	 vIncFTF.setEditable(true);
    	  dpdtFTF.setEditable(false);	 dtdvFTF.setEditable(true);
      }
       
      frame.setVisible(true);
    } catch (org.omg.CORBA.COMM_FAILURE     noServer) {
      JOptionPane.showMessageDialog(null, 
    	"Lost contact with server. Server is most likely down.\nPlease wait a few minutes and reload applet or restart application.",
    	"CORBA Server Error", JOptionPane.ERROR_MESSAGE);
    } catch (org.omg.CORBA.OBJECT_NOT_EXIST noObject) {
      JOptionPane.showMessageDialog(null, 
    	"Lost contact with server. Server has deleted your process.\nPlease reload applet or restart application.",
    	"CORBA Server Error", JOptionPane.ERROR_MESSAGE);
    }
  }
  
  private void addComponent(Container container, Component component, int gx, int gy, int gw, int gh, int fill){
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx      = gx;
    gbc.gridy      = gy;
    gbc.gridwidth  = gw;
    gbc.gridheight = gh;
    gbc.fill       = fill;
    container.add(component, gbc);
  }

  private class DoneHandler implements ActionListener {
    public void actionPerformed(ActionEvent ae){
      System.out.println("Entering the Done ActionListener.");      
      frame.setVisible(false);
    }
  }
  
  private class ComputeHandler implements ActionListener {
    public void actionPerformed(ActionEvent ae){
      System.out.println("Entering the Compute ActionListener.");
      
      // TODO - Implementation
      
    }
  }
  
  private class TextHandler implements PropertyChangeListener {
    public void propertyChange(PropertyChangeEvent e) {
      JFormattedTextField source = (JFormattedTextField) e.getSource();
      if (rockRef == null) return;
      double value = ((Number) source.getValue()).doubleValue();
      try {
        if	(source == tStartFTF && value != tStartVal) { tStartVal = value; rockRef.setTk(value+273.15); }
        else if (source == tStopFTF  && value != tStopVal )   tStopVal  = value;
        else if (source == tIncFTF   && value != tIncVal  )   tIncVal	= value;
        else if (source == pStartFTF && value != pStartVal) { pStartVal = value; rockRef.setPa(value*1.0e9);  }
        else if (source == pStopFTF  && value != pStopVal )   pStopVal  = value;
        else if (source == pIncFTF   && value != pIncVal  )   pIncVal	= value;
        else if (source == dpdtFTF   && value != dpdtVal  )   dpdtVal	= value;
        else if (source == hStartFTF && value != hStartVal)   hStartVal = value;
        else if (source == hStopFTF  && value != hStopVal )   hStopVal  = value;
        else if (source == hIncFTF   && value != hIncVal  )   hIncVal	= value;
        else if (source == dpdhFTF   && value != dpdhVal  )   dpdhVal	= value;
        else if (source == sStartFTF && value != sStartVal)   sStartVal = value;
        else if (source == sStopFTF  && value != sStopVal )   sStopVal  = value;
        else if (source == sIncFTF   && value != sIncVal  )   sIncVal	= value;
        else if (source == dpdsFTF   && value != dpdsVal  )   dpdsVal	= value;
        else if (source == vStartFTF && value != vStartVal)   vStartVal = value;
        else if (source == vStopFTF  && value != vStopVal )   vStopVal  = value;
        else if (source == vIncFTF   && value != vIncVal  )   vIncVal	= value;
        else if (source == dtdvFTF   && value != dtdvVal  )   dtdvVal	= value;
      } catch (org.omg.CORBA.COMM_FAILURE     noServer) {
        JOptionPane.showMessageDialog(null, 
          "Lost contact with server. Server is most likely down.\nPlease wait a few minutes and reload applet or restart application.",
          "CORBA Server Error", JOptionPane.ERROR_MESSAGE);
      } catch (org.omg.CORBA.OBJECT_NOT_EXIST noObject) {
        JOptionPane.showMessageDialog(null, 
          "Lost contact with server. Server has deleted your process.\nPlease reload applet or restart application.",
          "CORBA Server Error", JOptionPane.ERROR_MESSAGE);
      }

    }
  }
  
}
