package caltool.view.schedule;

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

/****
 *
 * Class ScheduleAppointmentDialog provides a view of Appointment as an input
 * to the scheduleAppointment method.  Hence, the dialog is a view of both an
 * Appointment object as well as the scheduleAppointment method.  The
 * data-entry components of the dialog constitute the Appointment view.  The
 * 'OK' button is the view of the ScheduleAppointment method.
 *                                                                          <p>
 * The data components consist of JLabels, JTextFields, JComboBoxes,
 * JCheckBoxes, and a JTextArea.  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>
 * For organizational clarity, two of the rows in the ScheduleAppointment
 * Dialog are defined in separate classes.  These are the <a href=
 * RecurringInfoSubdialog.html> RecurringInfoSubdialog </a> and <a href=
 * RemindInfoSubdialog.html> RemindInfoSubdialog </a> classes.
 *                                                                          <p>
 * The companion model for ScheduleAppointmentDialog is the <a href=
 * "../schedule/Schedule.html"> Schedule </a> class, since Schedule has the
 * method that is invoked from the 'OK' button action listener.  See class <a
 * href= "OKScheduleAppointmentButtonListener.html">
 * OKScheduleAppointmentButtonListener </a> for details of how the
 * Schedule.scheduleAppointment method is invoked.
 *
 */
public class ScheduleAppointmentDialog extends CalendarToolWindow {

    /**
     * Construct this with the given Schedule as companion model.  Construct
     * the two subviews for recurring info and reminder info.
     */
    public ScheduleAppointmentDialog(Screen screen, Schedule schedule,
            CalendarToolUI calToolUI) {
        super(screen, schedule, calToolUI);

        recurringInfo = new RecurringInfoSubdialog(screen, this);
        remindInfo = new RemindInfoSubdialog(screen, this);

        /*
         * Set the maximum component height and width.  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 = 3000;
    }

    /**
     * Compose this in six parts: (1) a top part consisting of the title, date,
     * end date, start time, and duration components; (2) a part consisting of
     * recurring info components; (3) a middle part with category, location,
     * security, and priority; (4) reminder info components; (5) details
     * components; (6) the bottom row consisting of the 'OK', 'Clear', and
     * 'Cancel' buttons.
     */
    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 the content rows.
         */
        composeRows();

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

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

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

    /**
     * Compose each of the rows and add to the vertically laid out panel.
     * Put some around spacing between each row, in the form of a vertical
     * strut.
     */
    protected void composeRows() {
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeTopPart());
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeRecurringInfo());
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeMiddlePart());
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeRemindInfo());
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeDetails());
        panel.add(Box.createVerticalStrut(15));
        panel.add(composeButtonRow());
        panel.add(Box.createVerticalStrut(15));
    }

    /**
     * Compose the top part of the dialog, consisting of the title, date, start
     * time, end date, and duration.  The components are laid out in a
     * three-row vertical box.  The title row is on top; it is composed as a
     * horizontal box containing a JLabel and JTextField.  The second row of
     * top-part components is a horizontal box, composed in turn of two
     * horizontal boxes containing JLabel/JTextField pairs for the date and
     * start time.  The third row consists of a JLabel/JTextField pairs for the
     * end date and the duration.  The duration is in turn a horizontal box
     * consisting of a JLabel, and two vertical box JLabel/JTextField pairs for
     * the hour and minute components of the duration.
     */
    protected Box composeTopPart() {
        Box vbox = Box.createVerticalBox();

        vbox.add(composeTitleRow());
        vbox.add(Box.createVerticalStrut(15));
        vbox.add(composeStartDateRow());
        vbox.add(Box.createVerticalStrut(15));
        vbox.add(composeEndDateRow());

        return vbox;
    }

    /**
     * Compose the title row as an hbox with label and text field.
     */
    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);
        hbox.add(Box.createHorizontalStrut(15));
        return hbox;

    }
        
    /**
     * Compose the start date row using two pairs of labels and text fields.
     * Cf. <a href= "ScheduleEventDialg#composeStartAndEndDateRow()">
     * ScheduleEventDialg.composeStartAndEndDateRow </a>.
     */
    protected Box composeStartDateRow() {

        Box hbox = Box.createHorizontalBox();

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

        /*
         * Add them to the hbox and return it.
         */
        hbox.add(Box.createHorizontalStrut(15));
        hbox.add(startDateLabel);
        hbox.add(startDateTextField);
        hbox.add(Box.createHorizontalStrut(10));
        hbox.add(startTimeLabel);
        hbox.add(startTimeTextField);
        hbox.add(Box.createHorizontalStrut(15));
        return hbox;

    }

    /**
     * Compose the end date row using two pairs of labels and text fields.
     */
    protected Box composeEndDateRow() {

        Box hbox = Box.createHorizontalBox();

        /*
         * Construct the labels and text fields.  See internal comments in the
         * composeTitle method for further explanatory details.
         */ 
        endDateLabel = new JLabel("End Date:  ");
        endDateLabel.setForeground(Color.black);
        endDateLabel.setEnabled(false);

        endDateTextField = new JTextField(15);
        endDateTextField.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                endDateTextField.getFont().getSize())));
        endDateTextField.setEnabled(false);

        JLabel durationLabel = new JLabel("Duration:  ");
        durationLabel.setForeground(Color.black);
        durationTextField = new JTextField(15);
        durationTextField.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                durationTextField.getFont().getSize())));

        /*
         * Add them to the hbox and return it.
         */
        hbox.add(Box.createHorizontalStrut(15));
        hbox.add(endDateLabel);
        hbox.add(endDateTextField);
        hbox.add(Box.createHorizontalStrut(10));
        hbox.add(durationLabel);
        hbox.add(durationTextField);
        hbox.add(Box.createHorizontalStrut(15));
        return hbox;

    }

    /**
     * Have the recurring info subdialog compose itself.
     */
    protected Component composeRecurringInfo() {
        return recurringInfo.compose();
    }

    /**
     * Compose the middle part of the dialog, consisting of the category,
     * location, security, and priority.  The category and security are combo
     * boxes, laid out in a horizontal box.  Location and priority are also
     * combo boxes in a horizontal box.  Location is editable.  See the
     * description of <a href= "ScheduleEventDialog#composeTopPart()">
     * composeTopPart for a more detailed description of component layout.
     */
    protected Box composeMiddlePart() {
        Box vbox = Box.createVerticalBox();

        vbox.add(composeCategorySecurityRow());
        vbox.add(Box.createVerticalStrut(15));
        vbox.add(composeLocationPriorityRow());

        return vbox;
    }

    /**
     * Compose the category/seurity row using two pairs of labels and text
     * fields.
     */
    protected Box composeCategorySecurityRow() {
        Box hbox = Box.createHorizontalBox();

        JLabel categoryLabel = new JLabel("Category:  ");
        categoryLabel.setForeground(Color.black);
        categoryComboBox = new JComboBox();
        categoryComboBox.addItem("none");
        categoryComboBox.addItem("");
        categoryComboBox.addItem("Edit ...");
        categoryComboBox.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                categoryComboBox.getFont().getSize())));

        JLabel securityLabel = new JLabel("Security:  ");
        securityLabel.setForeground(Color.black);
        String[] selections2 =
            {"public", "title only", "confidential", "private"};
        securityComboBox = new JComboBox(selections2);
        securityComboBox.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                securityComboBox.getFont().getSize())));

        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 location/priority row using two pairs of labels and text
     * fields.
     */
    protected Box composeLocationPriorityRow() {
        Box hbox = Box.createHorizontalBox();

        JLabel locationLabel = new JLabel("Location:  ");
        locationLabel.setForeground(Color.black);
        locationComboBox = new JComboBox();
        locationComboBox.setEditable(true);
        locationComboBox.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                locationComboBox.getFont().getSize())));

        JLabel priorityLabel = new JLabel("Priority:  ");
        priorityLabel.setForeground(Color.black);
        String[] selections = {"must", "optional"};
        priorityComboBox = new JComboBox(selections);
        priorityComboBox.setMaximumSize(
            new Dimension(maxComponentWidth, (int)(maxComponentHeight *
                priorityComboBox.getFont().getSize())));

        hbox.add(Box.createHorizontalStrut(15));
        hbox.add(locationLabel);
        hbox.add(locationComboBox);
        hbox.add(Box.createHorizontalStrut(10));
        hbox.add(priorityLabel);
        hbox.add(priorityComboBox);
        hbox.add(Box.createHorizontalStrut(15));

        return hbox;

    }

    /**
     * Have the remind info subdialog compose itself.
     */
    protected Component composeRemindInfo() {
        return remindInfo.compose();
    }

    /**
     * Compose the details area as a labeled, scrolling text area.  The label
     * and the text area are in a left-aligned vbox.  The vbox is in a hbox
     * with horizontal spacing on each side
     */
    protected Box composeDetails() {
        Box hbox = Box.createHorizontalBox();
        Box vbox = Box.createVerticalBox();

        JLabel label = new JLabel("Details:");
        label.setForeground(Color.black);
        label.setAlignmentX(Box.LEFT_ALIGNMENT);
        detailsTextArea = new JTextArea(6, 40);
        JScrollPane scrollPane = new JScrollPane(detailsTextArea);
        scrollPane.setAlignmentX(Box.LEFT_ALIGNMENT);

        vbox.add(label);
        vbox.add(scrollPane);

        hbox.add(Box.createHorizontalStrut(15));
        hbox.add(vbox);
        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=
     * "OKScheduleAppointmentButtonListener.html">
     * OKScheduleAppointmentButtonListener </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 OKScheduleAppointmentButtonListener((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.  It also needs to be refined to clear the recurring and
     * remind check boxes and associated components.
     */
    protected void clear() {
        titleTextField.setText("");
        startDateTextField.setText("");
        endDateTextField.setText("");
        startTimeTextField.setText("");
        durationTextField.setText("");
        categoryComboBox.setSelectedItem("none");
        locationComboBox.setSelectedItem(null);
        securityComboBox.setSelectedIndex(0);
        detailsTextArea.setText("");
    }

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

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

    /** The (start) date label.  This needs to be a persistent data field since
        it changes from "Date" to "Start Date" for recurring appointments.
        Also, it has different text in the ScheduleMeetingDialog, subclass. */
    protected JLabel startDateLabel;

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

    /** The start time text field. */
    protected JTextField startTimeTextField;

    /** The end date label.  This needs to be a persistent data field since
        it's enabled or disabled depending on whether the appointment is
        recurring.  Also, it has different text in the ScheduleMeetingDialog,
        subclass.  */
    protected JLabel endDateLabel;

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

    /** The start time text field */
    protected JTextField durationTextField;

    /** Subview for recurring info */
    protected RecurringInfoSubdialog recurringInfo;

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

    /** The security combo box */
    protected JComboBox securityComboBox;

    /** The location combo box */
    protected JComboBox locationComboBox;

    /** The priority combo box */
    protected JComboBox priorityComboBox;

    /** Subview for recurring info */
    protected RemindInfoSubdialog remindInfo;

    /** The details text area */
    protected JTextArea detailsTextArea;

    /** 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;

}