/*
 * UserTableModel.java
 *
 * Created on 12. Juni 2001, 16:36
 */

package users.swing;

import util.*;
import util.swing.*;

import users.*;
import users.events.*;

import data.events.*;

import java.io.*;
import java.util.*;

/**
  * A {@link javax.swing.table.TableModel} that models the contents of a {@link UserManager}.
  *
  * @author Thomas Medack
  * @version 3.0 12/06/2001
  * @since v3.0
  */
public class UserTableModel extends AbstractTableModel implements UserDataListener,
                                                                  HelpableListener,
                                                                  Serializable {

    /**
      * The UserManager that is being modelled.
      *
      * @serial
      */
    protected UserManager m_umManager;
    
    /**
      * This abstract class is a special Comparator, which compares Users. It will be
      * used in the UserTableModel to define the order of elements in the assoziated 
      * JUserTable.
      * 
      * @serial
      */
    public static abstract class UserComparator {
        public abstract int compare (User obj, User obj1);
    }
    
    /**
      * The Comparator that defines the sorting order of records in the model. It compares
      * {@link CatalogItem CatalogItems}.
      *
      * @serial
      */
    protected UserComparator m_cmpComparator = new UserComparator() {
        public int compare (User obj, User obj1) {
            return new NaturalComparator().compare (obj.getName(), obj1.getName());
        }
    };
    
    /**
      * The internal model. A list of the Users' names.
      *
      * @serial
      */
    protected List m_lKeys;
    
    /**
      * Create a new UserTableModel.
      *
      * @param u the UserManager to be modelled. 
      * @param cmp a Comparator defining the sort order of the records. If <code>null</code>, records are ordered
      * according to the natural ordering of the Users.
      * @param ted a TableEntryDescriptor that can split individual Users into a table's cells.
      */
    public UserTableModel (UserManager u,
                           UserComparator cmp,
                           TableEntryDescriptor ted) {
        super (ted);
        
        m_umManager = u;

        if (cmp != null) {
            m_cmpComparator = cmp;
        }

        listenerList = new ListenerHelper (this);

        updateModel();
    }
    
    /**
      * Get the record at the given index.
      *
      * @param row the index for which to retrieve the record. Element of [0, {@link #getRowCount}).
      * @return the {@link User} to be displayed at the given index. May return <code>null</code> if
      * either there is no record at the indicated position or an exception occurs.
      *
      * @override Never
      */
    public Object getRecord (int row) {
        ((ListenerHelper) listenerList).needModelUpdate();

        if ((row > -1) && (row < getRowCount())) {
            return m_lKeys.get (row);
        }
        else {
            return null;
        }
    }

    /**
      * Get the number of records in this model.
      *
      * @override Never
      */
    public int getRowCount() {
        ((ListenerHelper) listenerList).needModelUpdate();

        return m_lKeys.size();
    }
    
    /**
      * Subscribe as a listener to the model.
      *
      * @override Never
      */
    public void subscribe() {
        m_umManager.addUserDataListener (this);
    }

    /**
      * Un-Subscribe as a listener from the model.
      *
      * @override Never
      */
    public void unsubscribe() {
        m_umManager.removeUserDataListener (this);
    }

    /**
      * Update the internal model based on the modelled {@link UserManager}.
      *
      * @override Never
      */
    public synchronized void updateModel() {
        List lKeys = new LinkedList (m_umManager.getUsers());
        Collections.sort (lKeys, new Comparator() {
            public int compare (Object o1, Object o2) {
                return m_cmpComparator.compare ((User)o1,
                                                (User)o2);
            }
        });

        m_lKeys = lKeys;
    }
    
    public void userAdded (UserDataEvent e) {
        updateModel();

        int nIdx = m_lKeys.indexOf (e.getUser());

        if (nIdx > -1) {
            fireTableRowsInserted (nIdx, nIdx);
        }
    }
    
    public void userDeleted (UserDataEvent e) {
        int nIdx = m_lKeys.indexOf (e.getUser());

        updateModel();

        if (nIdx > -1) {
            fireTableRowsDeleted (nIdx, nIdx);
        }
    }
}