import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;

/**
 * Creates a GUI with an input text area, an output
 * text area, and a button panel containing four
 * buttons, "New code", "Encode", "Decode", and
 * "Quit." Each button (except Quit) calls a method
 * in a CodeMachine object, and displays the result
 * in the output area.
 * 
 * @author David Matuszek
 * @version Oct 19, 2006
 */
public class SecretCode extends JFrame {
    private JPanel contentPanel;
    private JTextArea inputTextArea;
    private JTextArea outputTextArea;
    private JPanel buttonPanel;
    private JButton newCodeButton;
    private JButton encodeButton;
    private JButton decodeButton;
    private JButton quitButton;
    
    private SecretCode thisGui;
    private CodeMachine coder;
    
    private int width;
    private int height;
    
    /**
     * Constructor for SecretCode objects.
     * @param coder The CodeMachine object to be used when the
     *              GUI's buttons are clicked.
     */
    public SecretCode(CodeMachine coder) {
        this.coder = coder;
        width = 200;
        height = 150;
        createWidgets();
        createGui();
        attachListeners();
        thisGui = this;
        thisGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    /**
     * Creates all the GUI elements.
     */
    private void createWidgets() {
        contentPanel = new JPanel();
        buttonPanel = new JPanel();
        inputTextArea = new JTextArea();
        outputTextArea = new JTextArea();
        newCodeButton = new JButton("New code"); 
        encodeButton = new JButton("Encode");  
        decodeButton = new JButton("Decode"); 
        quitButton = new JButton("Quit");     
    }
    
    /**
     * Creates the main areas of the GUI and installs them.
     */
    private void createGui() {
        createContentArea();
        createButtonArea();
        setSize(width, height);
    }

    /**
     * Creates and installs the input and output text areas.
     */
    private void createContentArea() {
        setLayout(new BorderLayout());
        add(contentPanel, BorderLayout.CENTER);
        add(buttonPanel, BorderLayout.SOUTH);
        contentPanel.setLayout(new GridLayout(2, 1));
        contentPanel.add(makeScrollableArea(inputTextArea,
            "Input text"));
        contentPanel.add(makeScrollableArea(outputTextArea,
            "Output text"));
        inputTextArea.selectAll();
    }
    
    /**
     * Puts a titled border around the given text area, and adds
     * horizontal and vertical scroll bars as needed.
     * 
     * @param textArea The text area to be decorated.
     * @param title The title to put above the text area.
     * @return The decorated text area.
     */
    private JScrollPane makeScrollableArea(JTextArea textArea,
                                           String title) {
        Border lineBorder;
        TitledBorder titledBorder;
        // Make a panel containing a text area
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(textArea);
        // Make a titled scroll pane containing the panel
        JScrollPane scrollPane = new JScrollPane(panel);
        // Put the border and title around the scroll pane
        lineBorder = BorderFactory.createLineBorder(Color.black);
        titledBorder = BorderFactory.createTitledBorder(lineBorder, title);
        scrollPane.setBorder(titledBorder);
        scrollPane.setBackground(Color.WHITE);
        
        return scrollPane;
    }
    
    /**
     * Puts the buttons into the button panel.
     */
    private void createButtonArea() {
        buttonPanel.setLayout(new GridLayout(1, 4));
        buttonPanel.add(newCodeButton);
        buttonPanel.add(encodeButton);
        buttonPanel.add(decodeButton);
        buttonPanel.add(quitButton);
    }

    /**
     * Activates each of the buttons in the GUI. The variable "coder"
     * is an field of this object, whose value is an instance of
     * CodeMachine, and
     * <ul><li>New code -- calls coder.createNewCode(),</li>
     *     <li>Encode -- calls coder.encode(input),</li>
     *     <li>Decode -- calls coder.decode(input),</li>
     *     <li>Quit -- just quits the program.</li>
     * </ul>
     * where "input" is gotten from the input text area of the GUI.
     * Displays the result of each coder method in the output text area.
     */
    private void attachListeners() {
        newCodeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                String output = coder.createNewCode();
                outputTextArea.setText(output);
            }
        });
        decodeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                String input = inputTextArea.getText();
                String output = coder.decode(input);
                outputTextArea.setText(output);
            }
        });
        encodeButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                String input = inputTextArea.getText();
                String output = coder.encode(input);
                outputTextArea.setText(output);
            }
        });
        quitButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                System.exit(0);
            }
        });
    }
    
    /**
     * Creates the GUI, which takes over processing.
     * 
     * @param args Unused.
     */
    public static void main(String[] args) {
        CodeMachine coder = new CodeMachine();
        SecretCode window = new SecretCode(coder);
        window.setSize(400, 250);
        window.setVisible(true);
    }
}

