package users.stdforms;

import users.*;
import users.swing.*;

import sale.*;

import util.swing.*;

import javax.swing.*;
import javax.swing.event.*;

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

import java.util.*;

/**
  * FormSheet that can be used for log on procedures. The FormSheet will contain a
  * {@link javax.swing.JComboBox} allowing to select from a range of user names and optionally a password
  * input line.
  *
  * When the user clicks the "OK" button, the FormSheet checks if the password entered equals the
  * password of the user selected. Prior to this, the password will be garbled using
  * {@link User#garblePassWD the current global password garbler}. If the checking was successful,
  * {@link #getResult} will return the selected user, otherwise it will return <code>null</code>.<p>
  *
  * <p>A typical use sequence would look something like that:</p>
  *
  * <pre>
  *
  * ...
  * <b>LogOnForm lof = new LogOnForm ("Please log on",
  *                                "Select your user name:",
  *                                "Enter your password:",
  *                                true,
  *                                {@link UserManager#getGlobalUM UserManager.getGlobalUM()},
  *                                null,
  *                                null);</b>
  *
  * ...setFormSheet (lof);
  *
  * if (<b>lof.getResult() != null</b>) {
  *   // do log on of user lof.getResult
  * }
  * ...
  *
  * </pre>
  *
  * @author Steffen Zschaler
  * @version 2.0 28/07/1999
  * @since v2.0
  */
public class LogOnForm extends FormSheet {

  /**
    * The current user
    *
    * @serial
    */
  private User m_uCurrent;

  /**
    * The current password.
    *
    * @serial
    */
  private String m_sPassword;

  /**
    * True, if we asked a password.
    *
    * @serial
    */
  private boolean m_fAskPassWd;

  /**
    * Resulting user.
    *
    * @serial
    */
  private User m_uLogOnUser;

  /**
    * Create a new LogOnForm. Uses a {@link FormSheetContentCreator}.
    *
    * @param sCaption the caption of the {@link FormSheet}.
    * @param sUserPrompt a string prompting the user to select his/her user name.
    * @param sPassWdPrompt  a string prompting the user to enter his/her password. May be <code>null</code>
    * only if <i>fAskPassWd</i> is false.
    * @param fAskPassWd if false no password is needed and selection of the user name is sufficient.
    * @param um the UserManager that manages the users to select from. Normally the
    * {@link UserManager#getGlobalUM global UserManager}.
    * @param cmp a comparator that defines the order in which the user names appear. If <code>null</code>,
    * users will be ordered by their names.
    * @param uf a filter that allows only a subset of the users to be selected from. If <code>null</code>,
    * no filtering will occur.
    */
  public LogOnForm (String sCaption,
                    final String sUserPrompt,
                    final String sPassWdPrompt,
                    boolean fAskPassWd,
                    final UserManager um,
                    final Comparator cmp,
                    final UserFilter uf) {
    super (sCaption,
           (JComponent) null,
           true);

    m_fAskPassWd = fAskPassWd;

    addContentCreator (new FormSheetContentCreator() {
      protected void createFormSheetContent (FormSheet fs) {
        JPanel jpForm = new JPanel (new GridLayout (((m_fAskPassWd)?(2):(1)), 2));

        jpForm.add (new JLabel (sUserPrompt));

        UserComboBoxModel ucbmModel = new UserComboBoxModel (um, uf, cmp);

        JComboBox jcb = new JComboBox (ucbmModel);
        jcb.setRenderer (new JUserList.UserListCellRenderer());
        jcb.addItemListener (new ItemListener() {
          public void itemStateChanged (ItemEvent e) {
            if (e.getStateChange() == ItemEvent.SELECTED) {
              m_uCurrent = (User) e.getItem();
            }
            else {
              m_uCurrent = null;
            }
          }
        });

        jpForm.add (jcb);


        if (m_fAskPassWd) {
          jpForm.add (new JLabel (sPassWdPrompt));

          JTextField jtf = new JPasswordField();
          jtf.getDocument().addDocumentListener (new DocumentListener() {
            public void changedUpdate (DocumentEvent e) {
              try {
                m_sPassword = e.getDocument().getText (0, e.getDocument().getLength());
              }
              catch (javax.swing.text.BadLocationException ex) {}
            }

            public void insertUpdate (DocumentEvent e) {
              try {
                m_sPassword = e.getDocument().getText (0, e.getDocument().getLength());
              }
              catch (javax.swing.text.BadLocationException ex) {}
            }

            public void removeUpdate (DocumentEvent e) {
              try {
                m_sPassword = e.getDocument().getText (0, e.getDocument().getLength());
              }
              catch (javax.swing.text.BadLocationException ex) {}
            }
          });

          jpForm.add (jtf);
        }

        fs.setComponent (jpForm);
      }
    });
  }

  /**
    * Return the user that was selected if any. Return <code>null</code> if no user was selected, the password
    * was wrong or the FormSheet was cancelled. The value is only valid after the FormSheet was closed!
    *
    * @override Never
    */
  public User getResult() {
    return m_uLogOnUser;
  }

  /**
    * Overridden to check the password input and make sure the selected user can be returned by
    * {@link #getResult}.
    *
    * @override Never
    */
  public void ok() {
    if (m_uCurrent != null) {
      
      // If no input occurred, the password string is null. We don't want to run into a 
      // NullPointerException, so we come up with a dummy password.
      if (m_sPassword == null) {
        m_sPassword = "";
      }
      
      if ((!m_fAskPassWd) ||
          (m_uCurrent.isPassWd (User.garblePassWD (m_sPassword)))) {
        m_uLogOnUser = m_uCurrent;
      }
    }

    super.ok();
  }
}