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

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import java.lang.*;
import java.util.*;

class LostServerException extends Exception {
  public LostServerException () {}
  public LostServerException(String msg) { super(msg); }
}

public class UpdateRockTable {

  private static final int ROW = 25;
  private static final int COL = 10;

  private RockManager rManager;
  private RockTableModel rTableModel, dTableModel;
  private JComboBox rockPopupMenu;
  private JTable rTable, dTable;
  private FontMetrics fm;
  private Graphics gc;
  
  private int nDead        = 0;
  private int nActive      = 0;
  private int[] listActive = new int[ROW];
  private boolean updateTheDead = true;
  private String[] ior = new String[ROW];
  private String[] chn = new String[ROW];
  private String[] hip = new String[ROW];
  private String[] lac = new String[ROW];

  UpdateRockTable(RockManager rManager, RockTableModel rTableModel, RockTableModel dTableModel,
                  JTable rTable, JTable dTable) {
    this.rManager    = rManager;
    this.rTableModel = rTableModel;
    this.dTableModel = dTableModel;
    this.rTable      = rTable;
    this.dTable      = dTable;
    fm               = rTable.getFontMetrics(rTable.getFont());
    gc               = rTable.getGraphics();
  }
  
  public void popupDetails(int row, int col) {
    System.out.println("popupDetails called for row " + row + " and column " + col);
    if (row < nActive) {
      if (col == 0) {
        int response = JOptionPane.showConfirmDialog(null, "Delete selected instance of Rock class on server?",
	  "Delete class instance", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
	if (response == JOptionPane.YES_OPTION) {
	  System.out.println("Contacting server to kill row " + row);
	  try {
	    //rManager.apoptosize((short) listActive[row]);
	    rManager.remove((short) listActive[row]);
	  } catch (Exception e) {;}
	}
      } else if (col == 2) {
        String str = "Cannonical host name: " + chn[row] + "\nHost IP address: " + hip[row];
	JOptionPane.showMessageDialog(null, str, "Additional Information", JOptionPane.INFORMATION_MESSAGE);
      } else if (col == 4) {
        String str = "Time last accessed: " + lac[row];
	JOptionPane.showMessageDialog(null, str, "Additional Information", JOptionPane.INFORMATION_MESSAGE);
      } else {
        JOptionPane.showMessageDialog(null, "Sorry! No additional information is available on this item.",
	  "Additional Information", JOptionPane.INFORMATION_MESSAGE);
      }
    }
  }
  
  public void update() throws LostServerException {
    if (rManager != null && rTableModel != null && rTable != null) {
      
      // Create default widths of active and dead tables
      int[] colWidthA = new int[COL];
      colWidthA[0] = getLength("Status"     ); 
      colWidthA[1] = getLength("User"	   ); 
      colWidthA[2] = getLength("Host"	   ); 
      colWidthA[3] = getLength("Created"    ); 
      colWidthA[4] = getLength("Idle (secs)"); 
      colWidthA[5] = getLength("OS"	   ); 
      colWidthA[6] = getLength("Location"   ); 
      colWidthA[7] = getLength("Java"	   ); 
      colWidthA[8] = getLength("Java VM"    ); 
      colWidthA[9] = getLength("Java Spec"  );
      int[] colWidthD = new int[COL];
      for (int i=0; i<COL; i++) colWidthD[i] = colWidthA[i];
      
      int nRock = 0;
      try {
        RockStatus[] list = rManager.getStatus();
        nRock = (int) rManager.getNrock();
	
	// Add new entries to the dead table
	if (nActive > 0) {
	  for (int i=0; i<nActive; i++) {
  	    boolean foundIt = false;
	    for (int j=0; j<nRock; j++) if (listActive[i] == list[j].identifier) { foundIt = true; break; }
	    if (!foundIt) {
	      int[] cw = new int[COL];
	      cw[0] = getLength("dead");
              dTableModel.setValueAt("dead", nDead, 0);
	      for (int j=1; j<COL; j++) {
	        cw[j] = getLength((String) rTableModel.getValueAt(i, j));
	        dTableModel.setValueAt(rTableModel.getValueAt(i, j), nDead, j);
	      }
	      for (int j=0; j<COL; j++) if (colWidthD[j] < cw[j]) colWidthD[j] = cw[j];
	      nDead++;
	      updateTheDead = true;
	    }
	  }
	}

	nActive = 0;
        for (int i=0; i<nRock; i++) { // ior is an additional member
	  System.out.println("Rock identifier is " + list[i].identifier);
          int[] cw = new int[COL];
          Date timeCurrent	= new Date();
          Date timeCreated	= new Date((long) (list[i].timeCreated*1000));
	  Date timeLastAccessed = new Date((long) (list[i].timeLastAccessed*1000));
	  Integer timeDelta = new Integer( (int) (timeCurrent.getTime()/1000 - list[i].timeLastAccessed) );
	  String os_data   = list[i].client.os_name + " " + list[i].client.os_version + " (" + list[i].client.os_arch + ")";
	  String loc_data  = list[i].client.locale + " (" + list[i].client.time_zone + ")";
	  String java_data = ""; // list[i].client.java_vendor + " (" + list[i].client.java_version + ")";
	  String vm_data   = ""; // list[i].client.java_vm_name + " (" + list[i].client.java_vm_version + ", " 
	  		         // + list[i].client.java_vm_vendor + ")";
	  String js_data   = ""; // list[i].client.java_spec_name + " (" + list[i].client.java_spec_version + ", " 
	  		         // + list[i].client.java_spec_vendor + ")";
	
          rTableModel.setValueAt(list[i].status,	   i, 0); // Status
          rTableModel.setValueAt(list[i].client.user_name, i, 1); // User
          rTableModel.setValueAt(list[i].client.host_name, i, 2); // Host
          rTableModel.setValueAt(timeCreated.toString(),   i, 3); // Created
          rTableModel.setValueAt(timeDelta.toString(),     i, 4); // Idle time (secs)
          rTableModel.setValueAt(os_data,		   i, 5); // OS
          rTableModel.setValueAt(loc_data,		   i, 6); // Location
          rTableModel.setValueAt(java_data,		   i, 7); // Java
          rTableModel.setValueAt(vm_data,		   i, 8); // Java VM
          rTableModel.setValueAt(js_data,		   i, 9); // Java Spec
	  ior[i] = list[i].ior;
	  chn[i] = list[i].client.canonical_hostname;
	  hip[i] = list[i].client.host_address;
	  lac[i] = timeLastAccessed.toString();
	  
	  listActive[i] = list[i].identifier;
	  nActive++;
	
	  cw[0] = getLength(list[i].status	    );
	  cw[1] = getLength(list[i].client.user_name);
	  cw[2] = getLength(list[i].client.host_name);
	  cw[3] = getLength(timeCreated.toString()  );
	  cw[4] = getLength(timeDelta.toString()    );
	  cw[5] = getLength(os_data		    );
	  cw[6] = getLength(loc_data		    );
	  cw[7] = getLength(java_data		    );
	  cw[8] = getLength(vm_data		    );
	  cw[9] = getLength(js_data		    );
	
	  for (int j=0; j<COL; j++) if (colWidthA[j] < cw[j]) colWidthA[j] = cw[j];
        }
      } catch (Exception e) {
	JOptionPane.showMessageDialog(null, "Lost contact with dRockServer on host.",
	  "CORBA Server Error", JOptionPane.ERROR_MESSAGE);
	throw new LostServerException();
      }
      
      for (int i=nRock; i<rTableModel.getRowCount(); i++) {
        rTableModel.setValueAt("", i, 0);
        rTableModel.setValueAt("", i, 1);
        rTableModel.setValueAt("", i, 2);
        rTableModel.setValueAt("", i, 3);
        rTableModel.setValueAt("", i, 4);
        rTableModel.setValueAt("", i, 5);
        rTableModel.setValueAt("", i, 6);
        rTableModel.setValueAt("", i, 7);
        rTableModel.setValueAt("", i, 8);
        rTableModel.setValueAt("", i, 9);
      }
      
      double sum = 0.0;
      for (int i=0; i<COL; i++) sum += (double) colWidthA[i];
      if (sum < 720.0) for (int i=0; i<COL; i++) colWidthA[i] = (int) (((double) colWidthA[i])*720.0/sum);
      for (int i=0; i<COL; i++) rTable.getColumnModel().getColumn(i).setPreferredWidth(colWidthA[i]+8);
      
      if (updateTheDead) {
        sum = 0.0;
        for (int i=0; i<COL; i++) sum += (double) colWidthD[i];
        if (sum < 720.0) for (int i=0; i<COL; i++) colWidthD[i] = (int) (((double) colWidthD[i])*720.0/sum);
        for (int i=0; i<COL; i++) dTable.getColumnModel().getColumn(i).setPreferredWidth(colWidthD[i]+8);
	updateTheDead = false;
      }
      
    }
  }
  
  private int getLength(String str) {
    return (int) fm.getStringBounds(str, gc).getWidth();
  }
  
}  

