package com.example.model;
/**
   A Schedule object represents a collection of Events and is capable of
   determining a list of free times from the list of Events it contains. 
   @author Ryan Whited, Chris Sobona, Brian Hermann, Peter Park
   @version 2006-3-18
*/

public class Schedule
{
  /**
     Default contructor - initializes data
  */
  public Schedule()
  {
    // holds the events which include day, start, and end time
    week = new Event[maxEvents];

    // how many events are on the Schedule
    count = 0;

    // result[day of week] holds the formated data ready for output
    result = new String[7];

    // initializes result array to empty strings
    for(int i = 0; i < 7; i++)
      result[i] = "";

    // busyTimes [day of week] [24 hours] [60 mins]
    // busyTimes[day][hour][min] = 0: that min is free
    // busyTimes[day][hour][min] = 1: that min is busy
    busyTimes = new int[7][24][60];

    // initialize all minutes as free
    for(int a = 0; a < 7; a++)
      for(int b = 0; b < 24; b++)
    	  for(int c = 0; c < 60; c++)
    		  busyTimes[a][b][c] = 0;
  }

  /**
     @return the array of Events currently held by the Schedule
  */
  public Event[] getEvents()
  {
    return week;
  }

  /**
     Takes an Event, e, and adds that Event to the Schedule, updating the array
     of minutes.
     @param e the Event to add 
  */
  public void addEvent(Event e)
  {
    week[count] = e;
    count++;

    // update array of minutes
    for(int i = 0; i < count; i++)
      addToArray(week[i].getDay(), week[i].getStartTime(), week[i].getEndTime());
  }

  /**
     @return the number of Events currently in the Schedule
  */
  public int length()
  {
    return count;
  }

  /**
     @return the array of minutes
  */
  public int[][][] getFreeTimes()
  {
    return busyTimes;
  }

  /**
     @return array of formatted free times ready for output
  */
  public String[] getFormatedTime()
  {
    return result;
  }

  // Takes a day ID, a start time, and an end time, and updates the array
  // of minutes to reflect the newly added Event
  private void addToArray(int day, int start, int end)
  {
    // start hour = end hour
    if(start/100 == end/100)
    {
      for(int m = start%100; m < end%100; m++)
        busyTimes[day][start/100][m] = 1;
    }
    else // the event spans multiple hours
    {
      for(int h = start/100; h <= end/100; h++)
      {
        if(h == start/100)
        {
	  for(int m = start%100; m <= 59; m++)
	    busyTimes[day][h][m] = 1;
        }
	else if(h == end/100)
             {
               if (end%100 != 0)
               {
                 for(int m = 0; m < end%100; m++)
	           busyTimes[day][h][m] = 1;
               }
	     }
             else
             {
	       for(int m = 0; m <= 59; m++)
	         busyTimes[day][h][m] = 1;
	     }
      }
    }
  }

  /**
     Takes the Events contained by the calling Schedule and determines the
     available free times.
  */
  public void formatFreeTimes()
  {
    int min = -1;
    int max = -1;

    for(int d = 0; d < 7; d++)
    {
      for(int h = 0; h < 24; h++)
      {
	for(int m = 0; m < 60; m++)
        {
          if(busyTimes[d][h][m] == 0 && min == -1)
            min = (h * 100) + m;
          if(busyTimes[d][h][m] == 0 && max != -1)
          {
            min = (h * 100) + m;
            max = -1;
          }
          if(busyTimes[d][h][m] == 1 && min != -1)
          {
            max = (h * 100) + m;
            result[d] += timeConvert(min, max);
            min = -1;
          }
          if(h == 23 && m == 59 && min != -1)
            result[d] += timeConvert(min, 2400);
        }
      }
      min = -1;
      max = -1;
    }
  }

  /** Takes a minimum and maximum time (in military time) and returns a String
      in the format 11:00AM-2:30PM, where min=1100 and max=1430
      @param min the minimum time
      @param max the maximum time
      @return formatted String of the form 11:00AM-2:30PM
  */
  public static String timeConvert(int min, int max)
  {
	  int sHours = min / 100;
	  int sMin = min % 100;
	  int eHours = max / 100;
	  int eMin = max % 100;
	  String sAmPm = null;
	  String eAmPm = null;
	  String result = "";
	  // start am/pm
	  if((sHours < 12) || (sHours == 24))
		  sAmPm = new String("AM");
	  else 
		  sAmPm = new String("PM");
	  // end am/pm
	  if((eHours < 12) || (eHours == 24))
		  eAmPm = new String("AM");
	  else 
		  eAmPm = new String("PM");
	  // start hour
	  if(sHours > 12)
		  sHours = sHours % 12;
	  if(sHours == 0)
		  sHours = 12;
	  // end hour
	  if(eHours > 12)
		  eHours = eHours % 12;
	  if(eHours == 0)
		  eHours = 12;
	  
	  if(sMin < 10)
	  {
		  System.out.println("TESTA");
		  result += (sHours + ":0" + sMin + sAmPm + "-");
	  }
	  else
	  {
		  System.out.println("TESTB");
		  result += (sHours + ":" + sMin + sAmPm + "-");
	  }
	  if(eMin < 10)
	  {
		  result += (eHours + ":0" + eMin + eAmPm + ", ");
	  }
	  else
	  {
		  result += (eHours + ":" + eMin + eAmPm + ", ");
	  }
    return result;
  }

  /**
     Takes a start time and an end time in military time and sets a global
     constraint on the schedule for each day.
     @param start the start time
     @param end the end time
  */
  public void addGlobalConstraint(int start, int end)
  {
    for (int day = 0; day < 7; day++)
    {
      Event e1 = new Event(day, 0, start);
      Event e2 = new Event(day, end, 2400);
      this.addEvent(e1);
      this.addEvent(e2);
    }
  }
      
  private Event[] week;        // array of Events in this Schedule
  private int count;           // number of Events in this Schedule
  private int[][][] busyTimes; // array of minutes (0=free, 1=busy)
  private String[] result;     // array to hold computed free times

  // max number of events that can be stored
  private static final int maxEvents = 10080;
}
