// Date application using reference variables

#include <iostream>

#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;

// Function prototypes
bool isValidDate(int m, int d, int y);

void getRandomDate(int& m, int& d, int& y);
void printDate(const int& m, const int& d, const int& y);
int numberOfDaysInTheMonth(int m, int y);
void incrementDate(int& m, int& d, int& y);
int getTheDayOfTheYear(int m, int d, int y);

int main()
{
    srand(time(NULL));
    int month, day, year, i;
    cout << setfill('0');
    for (i = 0; i < 50; ++i)
    {
        getRandomDate(month,day,year);
        if (isValidDate(month,day,year))
        {
            printDate(month,day,year);
        }
        else
        {
            cout << "Bad date: " << setw(2) << month << setw(2) << day << setw(2) << year << endl;
        }
    }
}


bool  isValidDate(int m, int d, int y)
{
    if (y < 0 || y > 99) return false;
    if (m < 0 || m > 12) return false;
    if (d < 0 || numberOfDaysInTheMonth(m, y) < d) return false;
    return true;
}


void printDate(const int& m, const int& d, const int& y)
{
    int doy = getTheDayOfTheYear(m,d,y);
    cout << "The ";
    switch(doy%10)
    {
    case 1:
        cout << doy << "st day of the year, ";
        break;
    case 2:
        cout << doy << "nd day of the year, ";
        break;
    case 3:
        cout << doy << "rd day of the year, ";
        break;
    default:
        cout << doy << "th day of the year, ";
    }

    switch (m)
    {
    case 1:
        cout << "January";
        break;
    case 2:
        cout << "February";
        break;
    case 3:
        cout << "March";
        break;
    case 4:
        cout << "April";
        break;
    case 5:
        cout << "May";
        break;
    case 6:
        cout << "June";
        break;
    case 7:
        cout << "July";
        break;
    case 8:
        cout << "August";
        break;
    case 9:
        cout << "September";
        break;
    case 10:
        cout << "October";
        break;
    case 11:
        cout << "November";
        break;
    case 12:
        cout << "December";
        break;
    default:
        cerr << "Error: bad month = " << m << endl;
        exit(-5);
    }
    cout << ' ' << d << ", " << (y>49?1900:2000)+y << endl;
}


void getRandomDate(int& m, int& d, int& y)
{
    m = rand() % 12 + 1;
    d = rand() % 31 + 1;
    y = rand() % 99;
}


int numberOfDaysInTheMonth(int m, int y)
{
    if (m == 4 || m == 6 || m == 9 || m == 11) return 30;
    if (m != 2) return 31;
    else
    {
        if (y % 400 == 0) return 29;
        if (y % 100 == 0) return 28;
        if (y % 4 == 0) return 29;
    }
    return 28;
}


void incrementDate(int& m, int& d, int& y)
{
    if (numberOfDaysInTheMonth(m, y) == d)
    {
        d = 1;
        if (m == 12)
        {
            m = 1;
            ++(y);
        }
        else
        {
            ++(m);
        }
    }
    else
    {
        ++(d);
    }
}


int   getTheDayOfTheYear(int mon, int day, int year)
{
    int m = 1;
    int d = 1;
    int y = year;
    int doy = 1;

    while(!(m == mon && d == day && y == year))
    {
        ++doy;
        incrementDate(m,d,y);
    }
    return doy;
}