/*
 * Solution to Problem 2 (C++)
 * 14th Annual CS Programming Contest
 * WCU Dept of Math and CS
 * Copyright 2003 , All Rights Reserved
 *
 * Problem Statement:
 * Calendar Creator
 * Creates a calendar based on user input.  The user inputs 
 * a month and year, and the program creates a calendar for 
 * that month based on that input
 */

#include <iostream.h>
#include "apstring.h"
#include "apstring.cpp"

int computeDay(int month, int day);

main()
{
  int month;
  int year;
  int day;
  int dayOfWeek;
  apstring monthName;

  // Prompt for month and accept input 
  // (only accept in the range [1,12])
  // Loop until proper input is provided
  do {
    cout << "Enter the number for the month: ";
    cin >> month;
  }
  while (month < 0 || month > 12);
  cout << endl;

  // Prompt for year and accept input.  
  // Loop until proper input is provided
  do {
    cout << "Enter the year (4 digits): ";
    cin >> year;
  }
  while (year < 0 || year > 9999);

  //Compute day of week (0 == Su, 1 == Mo, etc.);
  dayOfWeek = computeDay(month, year);

  //Determine number of days in month
  int daysInMonth=0;
  switch (month) {
      case 1:   daysInMonth = 31;
                monthName = "January";
		break;
      case 2:   daysInMonth = 28; // Make leap yr adjustments below
                monthName = "February";
		break;
      case 3:   daysInMonth = 31;
                monthName = "March";
		break;
      case 4:   daysInMonth = 30;
                monthName="April";
		break;
      case 5:   daysInMonth = 31;
                monthName="May";
		break;
      case 6:   daysInMonth = 30;
                monthName="June";
		break;
      case 7:   daysInMonth = 31;
                monthName="July";
		break;
      case 8:   daysInMonth = 31;
                monthName="August";
		break;
      case 9:   daysInMonth = 30;
                monthName="September";
		break;
      case 10:  daysInMonth = 31;
                monthName="October";
		break;
      case 11:  daysInMonth = 30;
                monthName="November";
		break;
      case 12:  daysInMonth = 31;
                monthName="December";
		break;
     }
     //Handle lear year case for February
     if ((month == 2) && (year%4 == 0))
     {
       if ((year%100) != 0)  //Century months are not leap years 
            daysInMonth++;
       else if ((year%400) == 0) //Unless divisible by 400
            daysInMonth++;
      }
     
     //Declare and initialize variable for the date
     int date = 1;
     
     //Print headers for calendar
     cout <<  monthName <<  " " << year <<endl;
     cout << "Su \tMo \tTu  \tWe  \tTh  \tFr  \tSa" << endl;
     
     //Print out empty spaces on first row of calendar
     for (int i = 0; i<dayOfWeek; i++)
     {
       cout <<"\t";
     }
     //Print out rest of first row of calendar
     for (int i=dayOfWeek; i<7; i++)
     {
       cout << date <<  "\t";
        date++;
     }
     cout << endl;
     //Print out remainder of calendar
    for (int j=date; j<=daysInMonth; j+=7)
    {
        for (int k=0; k<7&&date<=daysInMonth; k++)
        {
	  cout << date << "\t";
            date++;
        }
        cout << endl;
    }
}

int computeDay(int month, int year)
  //Computes first day of the month for a particular year
{
  int a,y,m; //used for various adjustments during calculation
  int dayOfWeek;

  // We begin by setting up a number of variables needed 
  // to calculate the day of the week that the 
  // calendar begins on
  a=((14-month)/12); //a holds month mod
  y = year - a;
  m = month + (12*a) - 2; //m holds month part
     
   //Compute number representing day of week (0=Sunday, etc.)
  dayOfWeek = 1+ y;
  dayOfWeek += (y/4) - (y/100) + (y/400); //account for leap years
  dayOfWeek += (31*m)/12;  //Work through month calc
  dayOfWeek = dayOfWeek%7;  //Find remainder when dividing by 7 for 
                            //final result
  return dayOfWeek;
}

