package schedule;
import java.util.Collection;

/**
 * This file temporarily defines common objects that are used by the other
 * classes in the schedule package.  These classes are put in one file merely
 * as a temporary convenience during the initial stage of modelling.
 */

/**
 * RecurringInfo has components to specify the nature of a recurring item.  The
 * isRecurring component is an on/off flag that indicates whether an item
 * recurs.  The interval is one of Weekly, Biweekly, Monthly, or Yearly.  The
 * IntervalDetails component defines the precise means to define recurrence for
 * the different interval levels.
 */
abstract class RecurringInfo {
    boolean isRecurring;
    Interval interval;
    IntervalDetails details;
}

/**
 * Interval specifies the granularity at which recurring items are defined.
 * The Weekly and Biweekly settings allow the user to specify recurrence on one
 * or more days of the week.  The Monthly setting allows the user to specify
 * recurrence on one or more days in one or more weeks of each month.  The
 * Yearly setting allows the user to specify recurrence on one or more specific
 * dates in the year.
 */
enum Interval {
    Weekly, Biweekly, Monthly, Yearly
}

/**
 * IntervalDetails are either weekly or monthly.  This parent class is used
 * generically for either kind of details.
 */
abstract class IntervalDetails {}

/**
 * WeeklyDetails has an on/off setting for each day of the week on which
 * an item recurs.  These details are also used for the BiWeekly setting
 * of the recurrence interval.
 */
abstract class WeeklyDetails extends IntervalDetails {
    int onSun;
    int onMon;
    int onTue;
    int onWed;
    int onThu;
    int onFri;
    int onSat;
}

/**
 * MonthlyDetails can be specified on a day-of-the-week basis or on specific
 * date(s) basis.  The two extending classes have the specific details for these
 * two types of settings.  This parent class is used generically for either
 * kind of details.
 */
abstract class MonthlyDetails {}

/**
 * MonthlyDayDetails contains a weekly details component for each possible week
 * of a month.  The First- through ThirdWeekDetails are distinct for all
 * possible months.  Depending on the configuration of a particular month in a
 * particular year, there is potential conflict in specifying recurrence in the
 * fourth, fifth, or last weeks.  The conflicts are resolved as follows:
 *                                                                           <p>
 * For months with 4 weeks only, the settings in FifthWeekDetails do not apply,
 * and the settings in LastWeekDetails, if present, override any settings in
 * FourthWeekDetails.  For months with 5 weeks only, the settings in
 * LastWeekDetails, if present, override any settings in FifthWeekDetails.
 * (For months with 6 weeks, the LastWeekDetails component applies to the 6th
 * week, and there are no conflicts.)
 */
abstract class MonthlyDayDetails extends MonthlyDetails {
    WeeklyDetails firstWeekDetails;
    WeeklyDetails secondWeekDetails;
    WeeklyDetails thirdWeekDetails;
    WeeklyDetails fourthWeekDetails;
    WeeklyDetails fifthWeekDetails;
    WeeklyDetails lastWeekDetails;
}

/**
 * MonthlyDateDetails is a collection of zero or more specific dates in a month
 * on which an item recurs.
 */
abstract class MonthlyDateDetails extends MonthlyDetails {
    Collection<DateNumber> dates;
}

/**
 * Security is one of four possible levels, each of which is described
 * individually in the body of the enum.  The selected level specifies the
 * degree of visibility a scheduled item has to other users.  For an
 * appointment, task, or event, "other users" are defined as all users other
 * than the user on whose calendar the scheduled item appears.  For a meeting,
 * "other users" are defined as all users not on the Attendee list of the
 * meeting.
 */
enum Security {
   
    /**
     * Public security means other users can see the scheduled item and all the
     * information about the item.
     */
    Public,

    /*
     * PublicTitle security means other users can see the title of the
     * scheduled item but none of the other information about the item.
     */
    PublicTitle,

    /**
     * Confidential security means other users can only see that a user is
     * unavailable for the time period of a scheduled item; no other
     * information about the scheduled item is visible.  Since confidential
     * security applies to a specific time period, it is meaningful only for
     * appointments and meetings, not for tasks or events; tasks and events do
     * not have specific time components.
     */
    Confidential,
    
    /**
     * Private security means other users see no information at all about a
     * scheduled item, not even that the item is scheduled.  Note that private
     * security hides a scheduled item from the ScheduleMeeting operation,
     * q.v., so that a meeting may be scheduled at the same time as a private
     * appointment.  It is up to the user to handle this situation by
     * accepting or refusing the scheduled meeting.  Given the nature of
     * private security, it does not apply to meetings.  I.e., only
     * appointments can have private security.
     */
    Private
}

enum AppointmentSecurity {
    Public,
    PublicTitle,
    Confidential,
    Private
}

/**
 * For now a Location is a free-form string indicating in what physical
 * location an item is scheduled.  It may be refined to something like
 * (building,room) pair.
 */
abstract class Location {
    String value;
}

/**
 * An AppointmentPriority indicates whether an appointment is a must or if it
 * is optional.  This information is used to indicate the general importance of
 * an appointment to the user.  The operational use of AppointmentPriority is
 * in the ScheduleMeeting operation, where the meeting scheduler can elect to
 * consider optional appointments as allowable times for a meeting.
 */
enum AppointmentPriority {
    Must,
    Optional
}

/**
 * A TaskPriority is a positive integer that defines the priority of one
 * task relative to others.  It's defined as a separate class in case we want
 * to enforce the value range restriction within the class constructor.
 */
abstract class TaskPriority {
    int value;
}

/**
 * RemindInfo has a flag that indicates if a scheduled item will have a
 * reminder sent and defines one of three ways that the user is alerted when a
 * scheduled event is to occur.  OnScreen means the user is reminded with a
 * pop-up alert on her computer screen.  BeepOnly means the user is reminded
 * with a simple audible tone on the computer.  Email means the user is sent an
 * electronic mail message reminder.
 */
abstract class RemindInfo {
    boolean isReminded;
    HowReminded howReminded;
}

enum HowReminded {    
  OnScreen,
  BeepOnly,
  Email
}

/**
 * AppointmentRemindInfo extends RemindInfo by adding information for how
 * soon before a scheduled item the reminder is to be sent.  For appointments,
 * the time units are minutes, hours, or days (cf. TaskRemindInfo).
 */
abstract class AppointmentRemindInfo extends RemindInfo {
    double howSoonBefore;
    AppointmentReminderUnits units;
}

/**
 * TaskRemindInfo extends RemindInfo by adding information for how soon before
 * a task the reminder is to be sent.  For tasks, the time unit is days.  A
 * fractional day can be used for smaller granularity if desired.
 */
abstract class TaskRemindInfo extends RemindInfo {
    double howSoonBefore;
}

/**
 * Appointment reminders can come minutes, hours, or days before an
 * appointment.  The units for these can be fractional, for maximum
 * flexibility.
 */
enum AppointmentReminderUnits {
    MinutesBefore, HoursBefore, DaysBefore
}

/**
 * Attendees is a collection of names of those who attend a meeting.
 */
abstract class Attendees {
    Collection<String> names;
}

/**
 * MeetingMinutes is current defined as the URL for the location of the minutes
 * of a meeting.  This definition may be refined in upcoming versions of the
 * requirements.
 */
abstract class MeetingMinutes {
    String url;
}

/**
 * The details of the Text object are TBD.  It may just turn out to be a
 * plain string.  Or it may a limited form of HTML, so we can include linkable
 * URLs in it.
 */
abstract class Text {}

/**
 * The PossibleMeetingTimes object is a collection of (start time, start date)
 * pairs at which a meeting could be held.
 */
abstract class PossibleMeetingTimes {
    Collection<TimeAndDate> timesAndDates;
}

/**
 * A TimeAndDate object is an element of a possible meeting time list.
 */
class TimeAndDate {
    Time startTime;
    Date startDate;
}