package caltool.view.schedule;

import caltool.model.schedule.*;
import caltool.view.*;
import mvp.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/****
 *
 * Class ScheduleEventDialog provides a view of Event as an input to the
 * scheduleEvent method.  Hence, the dialog is a view of both an Event object
 * as well as the scheduleEvent method.  The data-entry components of the
 * dialog constitute the Event view.  The 'OK' button is the view of the
 * scheduleEvent method.
 *                                                                          <p>
 * The data components consist of JLabels, JTextFields, and a JComboBox.  The
 * 'OK', 'Clear', and 'Cancel' buttons are JButtons.  The description of the <a
 * href= "#compose()"> compose </a> method has details of how the components
 * are laid out in the dialog window.
 *                                                                          <p>
 * The companion model for ScheduleEventDialog is the <a href= "Schedule.html">
 * Schedule </a> class, since Schedule has the method that is invoked from the
 * 'OK' button action listener.  See class <a href=
 * "OKScheduleEventButtonListener"> OKScheduleEventButtonListener.html </a> for
 * details of how the Schedule.scheduleEvent method is invoked.
 *
 * @author Gene Fisher (gfisher@calpoly.edu)
 * @version  6feb04
 *
 */
public class ScheduleEventDialog extends CalendarToolWindow {

    /**
     * Construct this with the given Schedule as companion model.
     */
    public ScheduleEventDialog(Screen screen, Schedule schedule,
            CalendarToolUI calToolUI) {

        /*
         * Call the parent constructor.
         */
        super(screen, schedule, calToolUI);

        /*
         * Set the maximum component height and width.  These the height value
         * was empiricaly derived, i.e., I fiddled around with it while looking
         * at the display.  The width value is presumably as big as the biggest
         * screen we'll come across.  If not, deal with it.
         */
        maxComponentHeight = 1.9;
        maxComponentWidth = 2000;
    }

    /**
     * Compose this as a vertical Box of four rows.  Each row is a horizontal
     * Box.  The first row contains a labeled text field for the event title.
     * The second row has labeled text fields for the start and end dates.  The
     * third row has a labeled combo box for the category selection and a
     * labeled combol box for the event security.  Finally, the fourth row has
     * the 'OK', 'Clear', and 'Cancel' buttons.
     *                                                                      <p>
     * Vertical and horizontal struts are used for spacing among all of the
     * components.
     */
    public Component compose() {

        /*
         * Add a JPanel to this' window, which was created in the parent class'
         * constructor.  JPanel is the standard background container for
         * holding Swing components.
         */
        panel = new JPanel();
        window.add(panel);

        /*
         * Set the layout style of the panel to be a vertical box.
         */
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        /*
         * Compose each of the rows and add to the vertically laid out panel.
         * Put some spacing between each row, in the form of a vertical strut.
         */
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeTitleRow());
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeStartAndEndDateRow());
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeCategoryAndSecurityRow());
        panel.add(Box.createVerticalStrut(25));
        panel.add(composeButtonRow());
        panel.add(Box.createVerticalStrut(15));

        /*
         * Set the window titlebar.
         */
        window.setTitle("Schedule an Event");

        /*
         * Call JFrame.pack to have Java size up the window properly.
         */
        window.pack();

        /*
         * Return the window to the caller.
         */
        return window;
    }

    /*-*
     * Data collection methods.
     */

    /**
     * Return the title as a string.
     */
    public String getTitle() {
        return titleTextField.getText();
    }

    /**
     * Return the start date as a Date value.  Note that the Date model class
     * does the parsing.
     */
    public Date getStartDate() {
        return new Date(startDateTextField.getText());
    }

    /**
     * Return the end date as a Date value.  Note that the Date model class
     * does the parsing.
     */
    public Date getEndDate() {
        return new Date(startDateTextField.getText());
    }

    /**
     * Return selected category as a Category value.
     * does the parsing.
     */
    public Category getCategory() {
        return new Category((String) categoryComboBox.getSelectedItem());
    }

    /**
     * Return the security as a simple security value.
     */
    public SimpleSecurity getSecurity() {
        return SimpleSecurity.valueOf(
            (String) securityComboBox.getSelectedItem());
    }

    /**
     * Display the error messages in the given exception object in a modal
     * pop-up window.
     */
    public void displayErrors(ScheduleEventPrecondViolation errors) {

        int i;                  // Error array loop index

        /*
         * Stubbed out implementation to std err instead of pop-up window.
         */
        for (i = 0; i < errors.numberOfErrors(); i++) {
            System.err.println(errors.getErrors()[i]);
        }

    }

    /**
     * Compose the title row using a JLabel and JTextField.
     */
    protected Box composeTitleRow() {

        Box hbox = Box.createHorizontalBox();

        /*
         * Construct the label and text field.
         */ 
        JLabel label = new JLabel("Title:  ");
        titleTextField = new JTextField();

        /*
         * Set the label font color to black, since I don't care for the
         * default "Java blue".
         */
        label.setForeground(Color.black);

        /*
         * Set the max height of the text field to keep it from resizing
         * vertically in the vertical box layout of the panel.
         */
        titleTextField.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                titleTextField.getFont().getSize())));

        /*
         * Add the label and text field to the hbox and return it.  Use
         * horizontal struts for spacing.
         */
        hbox.add(Box.createHorizontalStrut(15));
        hbox.add(label);
        hbox.add(titleTextField);
        titleTextField.setAlignmentX(Component.RIGHT_ALIGNMENT);
        hbox.add(Box.createHorizontalStrut(15));
        return hbox;

    }

    /**
     * Compose the start/end date row using two pairs of JLabel and JTextField.
     */
    protected Box composeStartAndEndDateRow() {

        Box hbox = Box.createHorizontalBox();

        /*
         * Construct the labels and text fields.  See internal comments in the
         * composeTitle method for further explanatory details.
         */ 
        JLabel startLabel = new JLabel("Start Date:  ");
        startLabel.setForeground(Color.black);
        startDateTextField = new JTextField(15);
        startDateTextField.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight * 
                startDateTextField.getFont().getSize())));
        JLabel endLabel = new JLabel("End Date:  ");
        endLabel.setForeground(Color.black);
        endDateTextField = new JTextField(15);
        endDateTextField.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                startDateTextField.getFont().getSize())));

        /*
         * Add them to the hbox and return it.
         */
        hbox.add(Box.createHorizontalStrut(15));
        hbox.add(startLabel);
        hbox.add(startDateTextField);
        hbox.add(Box.createHorizontalStrut(10));
        hbox.add(endLabel);
        hbox.add(endDateTextField);
        hbox.add(Box.createHorizontalStrut(15));
        return hbox;

    }

    /**
     * Compose the category/security row using a JComboBox and JTextField, with
     * JLabels next to each.
     */
    protected Box composeCategoryAndSecurityRow() {

        Box hbox = Box.createHorizontalBox();

        /*
         * Construct the labels and text fields.  See internal comments in the
         * composeTitle method for further explanatory details.
         */ 
        JLabel categoryLabel = new JLabel("Category:  ");
        categoryLabel.setForeground(Color.black);
        categoryComboBox = new JComboBox();
        categoryComboBox.addItem("none");

        JLabel securityLabel = new JLabel("Security:  ");
        securityLabel.setForeground(Color.black);
        String[] selections = {"Public", "Private"};
        securityComboBox = new JComboBox(selections);

        /*
         * Add them to the hbox and return it.
         */
        hbox.add(Box.createHorizontalStrut(15));
        hbox.add(categoryLabel);
        hbox.add(categoryComboBox);
        hbox.add(Box.createHorizontalStrut(10));
        hbox.add(securityLabel);
        hbox.add(securityComboBox);
        hbox.add(Box.createHorizontalStrut(15));
        return hbox;

    }

    /**
     * Compose the buttons row with three JButtons.  The action listeners for
     * Clear and Cancel buttons are straightforward.  The action listener for
     * the OK button is responsible for communication with the Schedule model.
     * See the description of <a href= "OKScheduleEventButtonListener.html>"
     * OKScheduleEventButtonListener </a> for explanatory details.
     *
     */
    protected Box composeButtonRow() {

        Box hbox = Box.createHorizontalBox();

        /*
         * Construct the three buttons.
         */ 
        JButton okButton = new JButton("OK");
        JButton clearButton = new JButton("Clear");
        JButton cancelButton = new JButton("Cancel");

        /*
         * Attach the appropriate action listeners to each button.
         */
        okButton.addActionListener(
            new OKScheduleEventButtonListener((Schedule) model, this));

        clearButton.addActionListener(
            new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    clear();
                }
            }
        );

        cancelButton.addActionListener(
            new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    hide();
                }
            }
        );

        /*
         * Add them to the hbox and return it.
         */
        hbox.add(okButton);
        hbox.add(Box.createHorizontalStrut(30));
        hbox.add(clearButton);
        hbox.add(Box.createHorizontalStrut(30));
        hbox.add(cancelButton);
        return hbox;

    }

    /**
     * Clear each of the text fields of this to empty.  Reset the combo box to
     * no selection.  NOTE: This method needs to be refined to use default 
     * values for clearing, once options and defaults functionality is
     * implemented.
     */
    protected void clear() {
        titleTextField.setText("");
        startDateTextField.setText("");
        endDateTextField.setText("");
        categoryComboBox.setSelectedIndex(0);
        securityComboBox.setSelectedIndex(0);
    }

    /** The background panel of this */
    protected JPanel panel;

    /** The title text field */
    protected JTextField titleTextField;

    /** The start date text field */
    protected JTextField startDateTextField;

    /** The end date text field */
    protected JTextField endDateTextField;

    /** The Categories combo box */
    protected JComboBox categoryComboBox;

    /** The security text field */
    protected JComboBox securityComboBox;

    /** The max height of a text field or combobox; this is necessary since
        these components stretch when the outer frame is resized, and look very
        funky when they do. */
    protected final double maxComponentHeight;

    /** The max width of any component; this is only necessary because the max
        height cannot be set separately, so we must pick some max width. */
    protected final int maxComponentWidth;

}