package view;

import java.util.Collection;
import schedule.DateNumber;
import schedule.Time;
import schedule.Duration;
import schedule.Category;

/**
 * A DailyAgenda has a full day name and a list of time-slot descriptors.  The
 * FullDayName consists of the day name itself (e.g., Wednesday), the month,
 * the date, and the year.  Each item in the TimeSlotDescriptor list consists
 * of a starting time (e.g., 8 AM) and a list of zero or more scheduled items.
 */
abstract class DailyAgenda {
    FullDayName name;
    Collection<TimeSlotDescriptor> times;
}

/**
 * A FullDayName has the complete and unique designation of a calendar day.
 */
abstract class FullDayName {
    DayName day;
    MonthName month;
    DateNumber date;
    YearNumber year;
}

enum DayName {
    Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
}

enum MonthName {
    January, February, March, April, May, June,
    July, August, September, October, November, December
}

/**
 * A time slot descriptor represents one slot (physically, a row) in a daily
 * agenda.  The TimeSlotName component is the start time for the slot.  The
 * list of BriefItemDescriptors contains the items that begin within the slot,
 * where "within" is defined as the start time plus the current time increment.
 * The overlaps component is a list of items with start times that overlap with
 * an item in the BriefItemDescriptor list.
 */
abstract class TimeSlotDescriptor {
    TimeSlotName slotName;
    Collection<BriefItemDescriptor> itemDescriptors;
    Overlaps overlaps;
}

/**
 * A TimeSlotName consists of a numeric TimeValue and an AmOrPm indicator.
 * TO DO: this definition should be reconciled as appropriate with the
 * definition of Time in schedule.java.
 */
abstract class TimeSlotName {
    int timeValue;
    AMorPM amOrPm;
}

/**
 * A brief item descriptor contains a subset of the information for a full
 * scheduled item.  The information is a Title, StartTime, Duration, and
 * Category.
 */
abstract class BriefItemDescriptor {
    String title;
    Time startTime;
    Duration duration;
    Category category;
}

/**
 * Overlaps contain zero or more BriefItemDescriptors that overlap with with
 * the master item in a given time slot.  An overlapping item is one with a
 * start time within the same time slot as other items.  The "master" item in a
 * time slot is the item that is first in a sorted order based on start time,
 * duration, and alphabetic title as the primary, secondary, and tertiary sort
 * keys, respectively.
 */
abstract class Overlaps {
    Collection<BriefItemDescriptor> descriptors;
}

abstract class DailyFormatOptions {
    NormalTimeRangeOption normalTimeRangeOption;
    TimeIncrementOption timeIncrementOption;
    int incrementHeightOption;
    ShowOrHide showHide24HoursOption;
    ShowOrHide showHideExactTimeOption;
    ShowOrHide showHideDashedLinesOption;
    ShowOrHide showHideExtensionArrowsOption;
    OnOrOff proportionalSpacingOnOffOption;
    DisplayOverlapsOption displayOverlapsOption;
    DefaultHeightAndWidthOption defaultHeightAndWidthOption;
}

abstract class NormalTimeRangeOption {Time startTime; Time endTime;}
abstract class TimeIncrementOption {int hours; int minutes;}
enum ShowOrHide {Show, Hide}
enum OnOrOff {On, Off}
enum DisplayOverlapsOption {Horizontal, Vertical}
abstract class DefaultHeightAndWidthOption {int height; int Width;}


abstract class Hour {
    int value;   // Must be legal hour value
}

abstract class Minute {
    int value;   // Must be legal minute value
}

enum AMorPM { AM, PM }

abstract class WeeklyAgendaTable {
    FullWeekName name;
    Collection<WeeklyTimeSlot> slots;
}

abstract class FullWeekName {
    MonthName month;
    DateNumberRange dateRange;
    YearNumber year;
}

abstract class DateNumberRange {
    DateNumber start;
    DateNumber end;
}

abstract class WeeklyTimeSlot  {
    Collection<WeeklyItemDescription> items;
}

abstract class WeeklyItemDescription {
    DayName day;
    TimeRange range;
    String truncatedTitle;
}

abstract class TimeRange {
    Time start;
    Time end;
}

abstract class WeeklyAgendaList {
    FullWeekName name;
    Collection<DailyItemList> items;
}

abstract class DailyItemList {
    DayName name;
    DateNumber date;
    Collection<DailyItemDescription> items;
}

abstract class MonthlyAgenda {
    FullMonthName name;
    DayName firstDay;
    NumberOfDaysPerMonth numberOfDays;
    Collection<DailyItemDescription> items;
}

abstract class DailyItemDescription {
    String value;       // to be refined
}

abstract class FullMonthName {
    MonthName month;
    YearNumber year;
}

class NumberOfDaysPerMonth {
    int value;   // Must be between 28 and 31, inclusive
}

abstract class YearlyCalendar {
    YearNumber year;
    Collection<SmallMonthView> months;
}

abstract class SmallMonthView { /* ... */ }

/**
 * A YearNumber is a positive integer between 0 and 9999.  It's defined as a
 * separate class in case we want to enforce the value range restriction within
 * the class constructor.
 */
abstract class YearNumber {
    int value;
}

/*
 * Model operations to place in the appropriate class:
 *
DailyAgenda viewDay(Calendar);
WeeklyAgendaTable viewWeekTable(Calendar);
WeeklyAgendaList viewWeekList(Calendar);
MonthlyAgenda viewMonth(Calendar);
YearlyCalendar viewYear(Calendar);
 *
 */