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");
            }
        }
    }
}
