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

import java.io.*;

import java.util.*;

import javax.swing.*;


public abstract class AuthenticatingFrame extends JFrame {
    public static final String MAIN_PANEL = "main";
    public static final String LOGIN_PANEL = "login";
    private JPanel cards;
    private JPanel contentPane;
    private LoginForm loginForm;

    private void setGui() {
	try {
	    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    cards = new JPanel(new CardLayout());
	    setContentPane(cards);
	    loginForm = new LoginForm(new Authenticator());
	    contentPane = new JPanel();
	    cards.add(loginForm, LOGIN_PANEL);
	    cards.add(contentPane, MAIN_PANEL);
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    /**
     * Return the Container that is shown when
     * successful login has occurred
     *
     * @return The main, authenticated content pane Container
     */
    @Override
	public Container getContentPane() {
	    return contentPane;
	}

    /**
     * Testing purposes - here follows an example usage
     *
     * @param args DOCUMENT ME!
     */
    public static void main(String[] args) {
	try {
	    SwingUtilities.invokeAndWait(new Runnable() {
		public void run() {
		    AuthenticatingFrame f = new AuthenticatingFrame() {
			// Override allow, per spec
			public boolean allow(String username, char[] pw) {
			    // An example of the worst kind of credential practice
			    return "admin".equals(username) && "admin".equals(new String(pw));
			}
		    };
		    f.setGui();
		    f.getContentPane()
		.add(new JLabel("Congratulations - you're logged in!"));
	    f.pack();
	    f.setVisible(true);
		}
	    });
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    /**
     * This is the method that authenticates the user,
     * called by the login Action and this must be overridden appropriately
     *
     * @param userName The user name
     * @param password The password
     *
     * @return Whether login was successful
     */
    public abstract boolean allow(String userName, char[] password);

    private class Authenticator extends AbstractAction {
	/**
	 * This Action authenticates the user and forwards
	 * the focus to the main content pane if successful.
	 * It does this by calling the allow method of the
	 * containing frame.
	 *
	 * @param e The ActionEvent from the login button
	 */
	public void actionPerformed(ActionEvent e) {
	    if (allow(loginForm.getUserName(), loginForm.getPassword())) {
		CardLayout cl = (CardLayout) (cards.getLayout());
		cl.show(cards, MAIN_PANEL);
	    } else {
		System.out.println("FAILED");
	    }
	}
    }
}

