package noriega.expresso.client;
import noriega.expresso.protocols.*;
import noriega.expresso.structures.Header;
import noriega.expresso.structures.Message;
import noriega.expresso.structures.BinaryFlag;
import noriega.expresso.structures.EmailAddress;
import noriega.expresso.server.ExpressoServer;
import noriega.expresso.server.ServiceDirectory;
import noriega.expresso.server.*;

import noriega.expresso.protocols.IMAPService;
import noriega.expresso.protocols.SmtpService;
import noriega.expresso.protocols.FlagService;

import javax.swing.table.AbstractTableModel;
import java.rmi.RemoteException;
import javax.swing.table.*;
import java.util.Vector;
import java.util.Date;
import javax.swing.JCheckBox;
import java.util.Collection;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

import noriega.util.*;

public class MyTableModel extends AbstractTableModel {
	
    private EmailAddress fromAddress;
    private EmailAddress toAddress;
    private String       subject;
    private Date         date;
    //FROM THE TESTCLIENT.JAVA FILE
    //*****************************
    ExpressoServer es;
    ServiceDirectory sd;
    IMAPService imap;
    SmtpService smtp;
    FlagService flags;
    //*****************************
    
    String urg = "Urgent";
    String resp = "Respond";
    Date d = new Date();
    
    final int START_NUM_ROWS = 0;
    private int numRows = 0;
    private int nextEmptyRow = 0;
    private boolean empty = true;
    
    final Vector columnNames;
    
    protected Vector data = null;
    
    public MyTableModel(ExpressoServer es,
			ServiceDirectory sd,
			IMAPService imap,
			SmtpService smtp,
			FlagService flags) {
	this.es = es;
	this.sd = sd;
	this.imap = imap;
	this.smtp = smtp;
	this.flags = flags; 
	
	
        data = new Vector();
	columnNames = new Vector(); 	} 	 	
    
    public void setData(Set s) {	
	if (!empty) { clear(); empty = false; }
	    try { 	
		columnNames.addElement("From");
		columnNames.addElement("To");
		columnNames.addElement("Subject");
		columnNames.addElement("Date");
		columnNames.addElement("New");
		columnNames.addElement("Unseen");
		String flagnames[] = flags.getFlagNames();
		
		int xyz = 0;
		
		if(flagnames == null) xyz = 0;
		else xyz = flagnames.length;
	       
		
		for(int ii=0; ii < xyz; ii++) 
		    columnNames.addElement(flagnames[ii]);	

		Iterator i = s.iterator();
		Message m;
		Header h;
		
		while( i.hasNext() ) {

		    /*
		    Vector next = new Vector();
		    h = (Header) i.next();
		    
		    next.addElement(h.getFrom().toString());
		    next.addElement(h.getTo().toString());

		    next.addElement(h.getSubject());
		    next.addElement(h.getDate());    
		    m = imap.fetchMessage((Header) i.next());
		    next.addElement( m.isRead() );
		    next.addElement( m.isNew()  );
		    //HashSet flag = m.
                    */
		    data.addElement(imap.fetchMessage((Header) i.next()));
 		    numRows++;
		    System.err.println("Message #" + numRows);
		    
		}
		

	    } 
            catch (RemoteException e) { 
		e.printStackTrace();
	    } 
	    fireTableStructureChanged();
	    fireTableDataChanged();
    }
    
    public int getColumnCount() {    
	DEBUG.debug ("ASKED FOR COLUMN COUNT");
	return columnNames.size();
	}    
    
    public int getRowCount() {        
	DEBUG.debug ("ASKED FOR ROW COUNT");
	return data.size();    
    }
    public String getColumnName(int col) {        
	DEBUG.debug ("Asked for column name " + col);
		return (String) columnNames.elementAt(col);    }
    
    public Object getValueAt(int row, int col) {	
	DEBUG.debug ("Asked for (" + row + "," + col + ")");

	if(col > columnNames.size() ||
	   row > data.size()         ){ return null; }
		
	switch (col) {
	case 0:
	    return getValuesAt(row).getHeader().getFrom();
	    
	case 1:
	    return getValuesAt(row).getHeader().getTo();
	    
	case 2:
	    return getValuesAt(row).getHeader().getSubject();
				
	case 3:
	    return getValuesAt(row).getHeader().getDate();
	    
	case 4:
	    return new Boolean(getValuesAt(row).isNew());
	    
	case 5:
	    return new Boolean(getValuesAt(row).isRead());
	    
	default:
	    try {
		return new Boolean ( 
		   ((BinaryFlag) flags.getFlag(
			(String) columnNames.elementAt(col))).getState()
		   );
	    } catch (RemoteException e) {
		return null;
	    }
	}
	
    }
    
    public Message getValuesAt(int row) {        
	DEBUG.debug ("CALLED VAL AT");
	return (Message) data.elementAt(row);
    }
    public Class getColumnClass(int c) {
	DEBUG.debug ("CALLED CC");
        return getValueAt(0, c).getClass();    
    }    
    /*
     * Don't need to implement this method unless your table's     
     * editable.
     */    
    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.        
	if (col < 4) { 
            return false;        
	} else {            
	    return true;        
	}    
    }
    
    /*     
     * Don't need to implement this method unless your table's
     * data can change.     
     */
    public void setValueAt(Object value, int row, int column) {
	data.setElementAt(value, row);
        
    }
    
    public void selectMailbox(HashSet header) {
	DEBUG.debug ("SELECTED aND CLEARED");
	clear();
	
    }
    
    
    //***************************************
    // ******** From the bingo game 
    //*************************
    
    /*
      public synchronized void updateMessage(Message m, int row) {
      int ID = playerRecord.ID; //find the ID
      PlayerRecord p = null;
      int index = -1; 
      boolean found = false;
      boolean addedRow = false;
      
      int i = 0;
      while (!found && (i < nextEmptyRow)) {
      p = (PlayerRecord)data.elementAt(i);
      if (p.ID == ID) {
      found = true;
      index = i;
      } else {
      i++;
      }
      }
      
      if (found) { //update old player
      data.setElementAt(playerRecord, index);
      } else { //add new player
      if (numRows <= nextEmptyRow) {
      //add a row
      numRows++;
      addedRow = true;
      }
      index = nextEmptyRow;
      data.addElement(playerRecord);
      }
      
      nextEmptyRow++;
      
      //Notify listeners that the data changed.
      if (addedRow) {
      fireTableRowsInserted(index, index);
      } else {
      fireTableRowsUpdated(index, index);
      }
      } 	*/
	
	public synchronized void clear() {
	    int oldNumRows = numRows;
	    
	    numRows = START_NUM_ROWS;
	    data.removeAllElements();
	    nextEmptyRow = 0;
	    
	    if (oldNumRows > START_NUM_ROWS) {
		fireTableRowsDeleted(START_NUM_ROWS, oldNumRows - 1);
	    }
	    fireTableRowsUpdated(0, START_NUM_ROWS - 1);
	}
    
    
} // end table model













