//
//
//  Pairs.cc
//
//      AUTHOR: Russell Lowke
//         T.F: Francis Crick
//  CSCIE-s111: Unit Five, Main - question 1 [worth 12pts],  7/17/2002
//
// Description: Write a program that reads the file thousand.wrd
//				and writes an alphabetical list of all pairs of letters
//				that do NOT occur together in any of the words.
//				list each pair only once.
//
//       Usage: executing will open and count file "thousand.wrd"
//
//      Method: 
//             Pairs()  - constructor for Pairs class
//            ~Pairs()  - destructor for Pairs class
//          pairSeen()  - Flag on pGrid that a letter pair has been seen
//          openFile()  -  open file [pFileName] into pInStream
//         closeFile()  -  close pInStream
//          readFile()  - read file [pFileName]
//         printData()  - Print data for Pairs from pGrid
//         printGrid()  - Print grid of bools - useful for testing
//              
//              main()  - constructs object, opens file "thousand.wrd", 
//                        calls read, print, and close methods
//
//		 Notes: function getString() is in lib  "Utils.cc"
//

#include "Pairs.h"									// include header


//
//   Pairs class - counts pairs of letters in a file
//
class Pairs
{
	private :
	
        char *  pFileName;							// name of file being read
    ifstream	pInStream;							// in stream for file
        grid	pGrid;
		
      public:
       
                Pairs(char *filename); 				// constructor
                ~Pairs();							// destructor
        int		pairSeen(char prev, char c);
        int     openFile();							// generic open
       	int     readFile();							// open and read
        void    printData();						// display
        void 	printGrid();
        int     closeFile();						// generic close

};


//
//  constructor for Pairs class
//
Pairs :: Pairs (char * fileName)
{
	pFileName = fileName;							// store filename
        
    for(int i = 0; i < PAIRS; i++) {				// clear grid to false
    	for(int j = 0; j < PAIRS; j++) {
    		pGrid[i][j] = false;
    	}
    }
}


//
//  destructor for Pairs class
//  
Pairs :: ~Pairs()
{
}


//
// flag pGrid, showing that letter pair is seen
//
// Note: [prev] and [c] must be lower case chars
//
int Pairs :: pairSeen(char prev, char c)
{
    int x = prev - 'a';
    int y = c    - 'a';
    
    if ( (x >= 0 && x <= PAIRS)  && 
         (y >= 0 && y <= PAIRS) ) {					// ensure grid range
        pGrid[x][y] = true;							// assign
        return 0;
    } else {
        return -1;
    }
}

//
//  open file [pFileName] into pInStream
//
int Pairs :: openFile()
{
	// open file		
	pInStream.open(pFileName);
	
	// ensure file exists
	if (pInStream == NULL) {						// file not found
	
		cout << pFileName << " -- Input file not found!\n";
		return -1;									// readFile failed
		
	} else {										// file OK
	
		pInStream.unsetf(ios::skipws);				// unset skip whitespace	
		
		return 0;									// readFile worked
	}
}


//
//  close [pInStream]
//
int Pairs :: closeFile()
{
	pInStream.close();
	return 0;										// closeFile worked
}


//
//  read file [pFileName]
//
int Pairs :: readFile()
{
	char c    = '\0';								// char being read
	char prev = '\0';								// previous char	
		
	while (! pInStream.eof() ) {
        prev = c;									// save prev char
        pInStream >> c;								// get next char
        c = tolower(c);								// convert to lowercase
        
        if ( isalpha(c) && isalpha(prev) ) {		// ensure alpha chars
            if ( pairSeen(prev, c) == -1) {
                return -1;							// oh no... bad data
            }
            
            // "if 'qx' is such a pair, do not list 'xq'"
            if ( pairSeen(c, prev) == -1) {
                return -1;							// oh no... bad data
            }
        }
	}
	
	return 0;										// readFile worked
}


//
//  Print data for Pairs from [pGrid]
//
void Pairs :: printData()
{
    int counter = 0;
    
    cout << "\nUnused letter pairs:\n";
    for(int i = 0; i < PAIRS; i++) {				// print the grid
        for(int j = 0; j < PAIRS; j++) {
            if (pGrid[i][j] == false) {
                cout << (char) ( i + 'a' )			// convert to ascii		
                     << (char) ( j + 'a' )
                     << ' ';
                
                if (++counter > DSPLYWIDTH) {		// newline
                    cout << endl;
                    counter = 0;
                }
            }
        }
    }
    
    cout << endl;									// finishup
}


//
//  Print grid of bools - useful for testing
//
void Pairs :: printGrid()
{	
    for(int i = 0; i < PAIRS; i++) {				// print the grid
        for(int j = 0; j < PAIRS; j++) {
            cout << pGrid[i][j];
        }
        cout << endl;
    }
}


//
//  constructs object, opens file "thousand.wrd"
//  calls read, print, and close methods
//
int main()
{
	char fileName[MAXSTR];
	
	Pairs robot( "thousand.wrd" );					// construct Pairs robot
													// to open file "thousand.wrd"
									
	// getString("Name of your file: ", fileName, MAXSTR);
	// Pairs robot( fileName );
								
	if ( robot.openFile() == -1 ) {					// file not found
            exit(1);												
	}
	if ( robot.readFile() == -1 ) {					// bad data
            cout << "problem reading file " << fileName << endl;
            exit(1);
        } 
	robot.printData();
	robot.closeFile();
	
	exit(0);
}