//******************************************************************
// BirthdayCalls program
// A data file contains people's names, phone numbers, and birth
// dates.  This program reads a date from standard input, calculates
// a date two weeks away, and prints the names, phone numbers, and
// birthdays of all those in the file whose birthdays come on or
// before the date two weeks away
//******************************************************************
#include "datetype.h"
#include <iostream>
#include <fstream>    // For file I/O
#include <string>     // For string type

using namespace std;

struct PhoneType
{
    int    areaCode;
    string number;
};
struct EntryType
{
    string    firstName;
    string    lastName;
    PhoneType phone;
    DateType  birthDate;
};

void GetCurrentDate( DateType& );
void GetEntry( ifstream&, EntryType& );
void OpenForInput( ifstream& );
void PrintEntry( EntryType, DateType );

int main()
{
    ifstream  friendFile;    // Input file of friends' records
    EntryType entry;         // Current record from friendFile
                             //   being checked
    DateType  currentDate;   // Month, day, and year of current day
    DateType  birthday;      // Date of next birthday
    DateType  targetDate;    // Two weeks from current date
    int       birthdayYear;  // Year of next birthday
    int       count;         // Loop counter

    OpenForInput(friendFile);
    if ( !friendFile )
        return 1;

    GetCurrentDate(currentDate);
    targetDate = currentDate;
    for (count = 1; count <= 14; count++)
        targetDate.Increment();

    GetEntry(friendFile, entry);
    while (friendFile)
    {
        if (targetDate.Year() != currentDate.Year() &&
              entry.birthDate.Month() == 1)
            birthdayYear = targetDate.Year();
        else
            birthdayYear = currentDate.Year();
        birthday.Set(entry.birthDate.Month(), entry.birthDate.Day(),
                     birthdayYear);
        if (birthday.ComparedTo(currentDate) >= SAME &&
              birthday.ComparedTo(targetDate) <= SAME)
            PrintEntry(entry, birthday);
        GetEntry(friendFile, entry);
    }
    return 0;
}

//******************************************************************

void OpenForInput( /* inout */ ifstream& someFile )    // File to be
                                                       // opened
// Prompts the user for the name of an input file
// and attempts to open the file

// Postcondition:
//     The user has been prompted for a file name
//  && IF the file could not be opened
//         An error message has been printed
// Note:
//     Upon return from this function, the caller must test
//     the stream state to see if the file was successfully opened

{
    string fileName;    // User-specified file name

    cout << "Input file name: ";
    cin >> fileName;

    someFile.open(fileName.c_str());
    if ( !someFile )
        cout << "** Can't open " << fileName << " **" << endl;
}

//******************************************************************

void GetCurrentDate( /* out */ DateType& currentDate )   // Today's
                                                         //   date
// Reads the current date from standard input

// Postcondition:
//     User has been prompted for the current month, day, and year
//  && currentDate is set according to the input values

{
    int month;
    int day;
    int year;

    cout << "Enter current date as three integers, separated by"
         << " spaces: MM DD YYYY" << endl;
    cin >> month >> day >> year;
    currentDate.Set(month, day, year);
}

//******************************************************************

void GetEntry(
     /* inout */ ifstream&  friendFile,    // Input file of records
     /* out */   EntryType& entry      )   // Next record from file

// Reads an entry from file friendFile

// Precondition:
//     friendFile is open for input
// Postcondition:
//     IF input of the firstName member failed due to end-of-file
//         entry is undefined
//     ELSE
//         All members of entry are filled with the values
//         for one person read from friendFile

{
    char dummy;   // Used to input and ignore certain characters
    int  month;
    int  day;
    int  year;

    friendFile >> entry.firstName;
    if ( !friendFile )
        return;
    friendFile >> entry.lastName;

    friendFile >> dummy                       // Consume '('
               >> entry.phone.areaCode
               >> dummy                       // Consume ')'
               >> entry.phone.number;

    friendFile >> month
               >> dummy                       // Consume '/'
               >> day
               >> dummy                       // Consume '/'
               >> year;
    entry.birthDate.Set(month, day, year);
}

//******************************************************************

void PrintEntry( /* in */ EntryType entry,      // Friend's record
                 /* in */ DateType  birthday )  // Friend's birthday
                                                //   this year
// Prints the name, phone number, and birthday

// Precondition:
//     entry is assigned
// Postcondition:
//     entry.firstName, entry.lastName, entry.phone, and birthday
//     have been printed

{
    cout << entry.firstName << ' ' << entry.lastName << endl;
    cout << '(' << entry.phone.areaCode << ") "
         << entry.phone.number << endl;
    birthday.Print();
    cout << endl << endl;
}
