// metroNewYorkAreaCodes3.cpp
//
// Determines the location corresponding to a
// user-specified area code in the New York
// metropolitan area.
//
// Demonstrates appropriate use of while and do/while,
// with a break statement in a while loop.
// Demonstrates switch with return instead of break.

#include <iostream>
#include <string>

using namespace std;

bool decideLocation(int areaCode, string& location);
bool userSaysYes(string question);


/*
 * Prompts the user for an area code in the
 * New York metropolitan area, and outputs the
 * name of the location corresponding to the
 * user-specified area code,  If the area code is
 * invalid or unknown, this program echoes the
 * area code and asks, "Where on Earth is that?"
 *
 * Global variables:
 *    cin - an istream object for interactive input.
 *           cin is an external variable, declared
 *           in library header file <iostream>.
 *    cout - an ostream object for output to the terminal.
 *           cout is an external variable, declared
 *           in library header file <iostream>.
 */
int main()
{
   cout << "This program will tell you where people live, "
                       << "given their area codes." << endl;

   do  {
      // Prompt the user
      cout << "Enter an area code:>";

      // Input the area code and check validity:
      int areaCode;
      cin >> areaCode;
      if ( !cin )  {
         cout << "Error: non-numeric input." << endl;
         return 1;
      }  // if

      // Output the corresponding location:
      string location;
      if ( decideLocation(areaCode, location) )
         cout << location << "." << endl;
      else
         cout << areaCode
                   << "?  Where on Earth is that?"
                   << endl;

      // Finish reading the line, before calling userSaysYes:
      string restOfLine;
      getline(cin, restOfLine);

   } while( userSaysYes(                  // uses cin and cout
              "Do you want to enter another area code?") );
}  // function main


/*
 * bool decideLocation(int areaCode, string& location)
 *
 * Given an area code within the New York
 * metropolitan area, determines the name
 * of the corresponding location.
 *
 * Parameters:
 *    areaCode - an area code.
 *    location - a string variable into which
 *          this function puts the name of a
 *          New York area location.
 *       precondition:  none.
 *       postcondition:  location is the name
 *          of the location corresponding to
 *          areaCode, if areaCode is a valid
 *          area code within the New York
 *          metropolitan area.
 *          Otherwise, location is unchanged.
 *
 * Returns:
 *    true if areaCode is an area code of
 *    a location within the New York
 *    metropolitan area, false otherwise.
 */
bool decideLocation(int areaCode, string& location)
{
   switch ( areaCode )  {
      case 212:  case 917:  case 646:
         location = "Manhattan";
         return true;
      case 718:  case 347:
         location = "outer-borough New York City";
         return true;
      case 516:  case 631:
         location = "Long Island";
         return true;
      case 914:  case 845:
         location = "upstate";
         return true;
      case 201:  case 973:  case 908:  case 732:  case 609:
         location = "New Jersey";
         return true;
      case 203:  case 860:
         location = "Connecticut";
         return true;
      case 401:
         location = "Rhode Island";
         return true;
      default:
         return false;
   }  // switch
}  // function decideLocation


/*
 * bool userSaysYes(string question)
 *
 * Asks the user a yes/no question, expecting an
 * answer of "Y", "y", "N", "n".  Prompts the user
 * repeatedly, if necessary, after invalid answers,
 * until a valid answer is obtained.  Returns a
 * boolean indication of the user's answer.
 *
 * Parameter:
 *    question - A yes/no question.
 *
 * Global variables:
 *    cin - an istream object for interactive input.
 *           cin is an external variable, declared
 *           in library header file <iostream>.
 *       Preconditions:  The state of cin is true, and
 *           cin is ready to read the beginning of a line.
 *           (Any previous line has been completely read,
 *           including the end-of-line marker.)
 *       Postconditions:  The state of cin is still true,
 *           and one or more lines have been completely read.
 *           false otherwise.
 *    cout - an ostream object for output to the terminal.
 *           cout is an external variable, declared
 *           in library header file <iostream>.
 *       Precondition:  The state of cout is true.
 *       Postcondition:  The state of cout is still true.
 *
 * Returns:
 *    true if the user answers "Y" or "y",
 *    false of the user answers "N" or "n".
 */
bool userSaysYes(string question)
{
   cout << question << " (Y/N)>";

   string line;

   while ( true )  {
      getline(cin, line);

      if ( line == "Y"  ||  line == "y"
              ||  line == "N"  ||  line == "n" )
         break;

      cout << "Please enter Y or N:>";
   }  // while

   return (line == "y" || line == "Y");
}  // function userSaysYes