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

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.net.URL;

import javax.naming.*;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.*;
import javax.swing.table.*;

/**
 * Creates a popup dialog box with a GUI for configuring assimilation options.
 * @version 1.0 (August 2007)
 * @author Mark S. Ghiorso, OFM-Research Inc.
 */
public class AssimHandler implements ActionListener {

  private rock.dRock rockRef;
  private JFrame frame;
  private JTable availTable, inclTable, compTable, assimTable, propTable;
  private AvailableTM   availModel;
  private IncludedTM    inclModel;
  private ComponentTM   compModel;
  private AssimilantTM  assimModel;
  private ProportionsTM propModel;

  /**
   * Class initializer.
   * @param rockRef Reference to an instance of a server-side rock object.
   */
  public AssimHandler (rock.dRock rockRef) {
    this.rockRef = rockRef;
    Border etchedBdr = BorderFactory.createEtchedBorder();
    
    frame = new JFrame("Assimilant");
    frame.addWindowListener(new java.awt.event.WindowAdapter() {
        public void windowClosing(java.awt.event.WindowEvent e) {
          Frame f = (Frame) e.getSource();
    	  f.setVisible(false);
        }
      });
    Container cp = frame.getContentPane();
	  
    GridBagLayout gbl = new GridBagLayout();
    cp.setLayout(gbl);
    
    // Table of included phases to be assimilated
    inclTable = new JTable(inclModel = new IncludedTM());
    inclTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    ListSelectionModel inclSM = inclTable.getSelectionModel();
    inclSM.addListSelectionListener(new ListSelectionListener() {
      public void valueChanged(ListSelectionEvent e) {
        ListSelectionModel lsm = (ListSelectionModel) e.getSource();
	if (lsm.isSelectionEmpty()) {
	} else {
	  int selectedRow = lsm.getMinSelectionIndex();
	  // TODO delete selected row and update private list
	}
      }
    });
    inclTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    inclTable.setPreferredScrollableViewportSize(new Dimension(100,100));
    JPanel aPanel1 = new JPanel();
           aPanel1.setLayout(new BorderLayout());
           aPanel1.add(new JLabel("Assimilant phases"), BorderLayout.NORTH);
    JScrollPane aPanel1sp = new JScrollPane(inclTable);
	        aPanel1sp.setBorder(etchedBdr);
	   aPanel1.add(aPanel1sp, BorderLayout.SOUTH);
           aPanel1.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    addComponent(cp, aPanel1, 0, 0, 1, 1, GridBagConstraints.BOTH);
    
    // Table of potential phases to be assimilated
    availTable = new JTable(availModel = new AvailableTM());
    availTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    ListSelectionModel availSM = availTable.getSelectionModel();
    availSM.addListSelectionListener(new ListSelectionListener() {
      public void valueChanged(ListSelectionEvent e) {
        ListSelectionModel lsm = (ListSelectionModel) e.getSource();
	if (lsm.isSelectionEmpty()) {
	} else {
	  int selectedRow = lsm.getMinSelectionIndex();
	  // TODO add selected row to incl Table
	}
      }
    });
    availTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    availTable.setPreferredScrollableViewportSize(new Dimension(100,200));
    JPanel aPanel2 = new JPanel();
           aPanel2.setLayout(new BorderLayout());
           aPanel2.add(new JLabel("Assimilant phases"), BorderLayout.NORTH);
    JScrollPane aPanel2sp = new JScrollPane(availTable);
	        aPanel2sp.setBorder(etchedBdr);
	   aPanel2.add(aPanel2sp, BorderLayout.SOUTH);
           aPanel2.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    addComponent(cp, aPanel2, 0, 1, 1, 3, GridBagConstraints.BOTH);
    
    // Table of phase components (for a selected included phase)
    compTable = new JTable(compModel = new ComponentTM());
    compTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    compTable.setPreferredScrollableViewportSize(new Dimension(100,300));
    JPanel aPanel3 = new JPanel();
           aPanel3.setLayout(new BorderLayout());
           aPanel3.add(new JLabel("Selected Phase:"), BorderLayout.NORTH);
    JScrollPane aPanel3sp = new JScrollPane(compTable);
	        aPanel3sp.setBorder(etchedBdr);
	   aPanel3.add(aPanel3sp, BorderLayout.SOUTH);
           aPanel3.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    addComponent(cp, aPanel3, 1, 0, 1, 4, GridBagConstraints.BOTH);
    
    // Table of assimilant intensive properties
    assimTable = new JTable(assimModel = new AssimilantTM());
    assimTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    JPanel aPanel4 = new JPanel();
	   aPanel4.setLayout(new BorderLayout());
	   aPanel4.add(new JLabel("Total Assimilant Properties:"), BorderLayout.NORTH);
	   aPanel4.add(assimTable, BorderLayout.SOUTH);
           aPanel4.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    addComponent(cp, aPanel4, 0, 4, 1, 1, GridBagConstraints.BOTH);
    
    // Table of proportions of selected phase in assimilant
    propTable = new JTable(propModel = new ProportionsTM());
    propTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    TableColumn unitColumn = propTable.getColumnModel().getColumn(2);
    JComboBox propCB = new JComboBox();
              propCB.addItem("wt %");
	      propCB.addItem("vol %");
    unitColumn.setCellEditor(new DefaultCellEditor(propCB));
    JPanel aPanel5 = new JPanel();
	   aPanel5.setLayout(new BorderLayout());
	   aPanel5.add(new JLabel("Proportions of Selected Phase:"),
	               BorderLayout.NORTH);
	   aPanel5.add(propTable, BorderLayout.SOUTH);
           aPanel5.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
    addComponent(cp, aPanel5, 1, 4, 1, 1, GridBagConstraints.BOTH);
    
    JPanel aPanel7 = new JPanel(); 
           aPanel7.setLayout(new GridLayout(0, 2));
    
    JButton tb1 = new JButton("Done");
	    tb1.addActionListener(new DoneHandler());
    aPanel7.add(tb1); 
    
    JButton tb2 = new JButton("Clear"); 
	    tb2.addActionListener(new ClearHandler());
    aPanel7.add(tb2);
    aPanel7.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));  
    addComponent(cp, aPanel7, 0, 5, 2, 1, GridBagConstraints.BOTH);
     
    frame.pack();
    frame.setLocation(50, 50);
  }

  /**
   * Called to display assimilant dialog box.
   * @param e Action event that triggered display.
   */
  public void actionPerformed(ActionEvent e){
    frame.setVisible(true);
  }
  
  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 IncludedTM extends AbstractTableModel {
    private String columnNames[] = { "Included" };
    private java.lang.Object[][] data;
    
    IncludedTM() {
      data = new java.lang.Object[10][1];
      for (int i=0; i<10; i++) data[i][0] = "No ORB";
    }
   
    public int getColumnCount() {
      return columnNames.length;
    }
    
    public int getRowCount() {
      return data.length;
    }
    
    public String getColumnName(int col) {
      return columnNames[col];
    }
    
    public java.lang.Object getValueAt(int row, int col) {
      return data[row][col];
    }
    
    public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }
    
    public boolean isCellEditable(int row, int col) {
      return false;
    }
    
    public void setValueAt(java.lang.Object value, int row, int col) {
      System.out.println("Setting value at " + row + "," + col + " to " + value +
    			 " (an instance of " + value.getClass() + ")");
      data[row][col] = value;
      fireTableCellUpdated(row,col);
    }
  }
 
  private class AvailableTM extends AbstractTableModel {
    private String columnNames[] = { "Available" };
    private java.lang.Object[][] data;
    
    AvailableTM() {
      data = new java.lang.Object[10][1];
      for (int i=0; i<10; i++) data[i][0] = "No ORB";
    }
   
    public int getColumnCount() {
      return columnNames.length;
    }
    
    public int getRowCount() {
      return data.length;
    }
    
    public String getColumnName(int col) {
      return columnNames[col];
    }
    
    public java.lang.Object getValueAt(int row, int col) {
      return data[row][col];
    }
    
    public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }
    
    public boolean isCellEditable(int row, int col) {
      return false;
    }
    
    public void setValueAt(java.lang.Object value, int row, int col) {
      System.out.println("Setting value at " + row + "," + col + " to " + value +
    			 " (an instance of " + value.getClass() + ")");
      data[row][col] = value;
      fireTableCellUpdated(row,col);
    }
  }
 
  private class ComponentTM extends AbstractTableModel {
    private String columnNames[] = { "Components", "Mole Fraction" };
    private java.lang.Object[][] data;
    
    ComponentTM() {
      data = new java.lang.Object[10][2];
      for (int i=0; i<10; i++) for (int j=0; j<2; j++) data[i][j] = "No ORB";
    }
   
    public int getColumnCount() {
      return columnNames.length;
    }
    
    public int getRowCount() {
      return data.length;
    }
    
    public String getColumnName(int col) {
      return columnNames[col];
    }
    
    public java.lang.Object getValueAt(int row, int col) {
      return data[row][col];
    }
    
    public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }
    
    public boolean isCellEditable(int row, int col) {
      return (col == 0) ? false : true;
    }
    
    public void setValueAt(java.lang.Object value, int row, int col) {
      System.out.println("Setting value at " + row + "," + col + " to " + value +
    			 " (an instance of " + value.getClass() + ")");
      data[row][col] = value;
      fireTableCellUpdated(row,col);
    }
  }
 
  private class AssimilantTM extends AbstractTableModel {
    private String columnNames[] = { null, null };
    private java.lang.Object data[][] = { { "Mass (gm):",  new Double(0.0) },
                                          { "T (C):",      new Double(0.0) },
					  { "Increments:", new Double(0.0) }
					};
    
    AssimilantTM() { }
   
    public int getColumnCount() {
      return columnNames.length;
    }
    
    public int getRowCount() {
      return data.length;
    }
    
    public String getColumnName(int col) {
      return columnNames[col];
    }
    
    public java.lang.Object getValueAt(int row, int col) {
      return data[row][col];
    }
    
    public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }
    
    public boolean isCellEditable(int row, int col) {
      return (col == 0) ? false : true;
    }
    
    public void setValueAt(java.lang.Object value, int row, int col) {
      System.out.println("Setting value at " + row + "," + col + " to " + value +
    			 " (an instance of " + value.getClass() + ")");
      data[row][col] = value;
      fireTableCellUpdated(row,col);
    }
  }
 
  private class ProportionsTM extends AbstractTableModel {
    private String columnNames[] = { "Phase", "Proportion", "Units" };
    private java.lang.Object data[][] = { { "dummy",  new Double(0.0), "wt %" } };
    
    ProportionsTM() { }
   
    public int getColumnCount() {
      return columnNames.length;
    }
    
    public int getRowCount() {
      return data.length;
    }
    
    public String getColumnName(int col) {
      return columnNames[col];
    }
    
    public java.lang.Object getValueAt(int row, int col) {
      return data[row][col];
    }
    
    public Class getColumnClass(int c) {
      return getValueAt(0, c).getClass();
    }
    
    public boolean isCellEditable(int row, int col) {
      return (col == 0) ? false : true;
    }
    
    public void setValueAt(java.lang.Object value, int row, int col) {
      System.out.println("Setting value at " + row + "," + col + " to " + value +
    			 " (an instance of " + value.getClass() + ")");
      data[row][col] = value;
      fireTableCellUpdated(row,col);
    }
  }
 
  private class DoneHandler implements ActionListener {
    public void actionPerformed(ActionEvent e){
      System.out.println("Entering the Done ActionListener.");      
      frame.setVisible(false);
    }
  }
  
  private class ClearHandler implements ActionListener {
    public void actionPerformed(ActionEvent e){
      System.out.println("Entering the Clear ActionListener.");
      
      // TODO - Implementation
      
    }
  }
}

