// main.cpp
// CSI 2131 Asst 2b by Naim R. El-Far (naim@discover.uottawa.ca)
// CSI 2131 - Winter 2006 - Prof. L.M. Moura

#include <iostream>
#include <fstream>
#include <string>
#include "StudentRecord.h"
#include "DataFile.h"
#include "PrimaryIndex.h"
#include "SecondaryIndex.h"
#include "KeyList.h"
using namespace std;

int main() {
	//Print welcome message
	//---------------------
	cout << "CSI 2131 Asst 2b W06" << endl
		 << "--------------------" << endl
		 << endl;

	//-------------------------------------------
	//Step 1: Build primary and secondary indices
	//-------------------------------------------
	
	//Prompt user for data file name
	//------------------------------
	cout << "Please enter data file name (default: studentfile.txt): ";
	string dataFileName = "";
	getline(cin, dataFileName, '\n');
	if (dataFileName == "")
		dataFileName = "studentfile.txt";
	
	//Instantiate data file class with data file name
	//-----------------------------------------------
	DataFile studentDataFile(dataFileName);

	//Prompt user for primary index file name
	//---------------------------------------
	cout << "Please enter primary index file name (default: primaryindex.txt): ";
	string primaryIndexFileName = "";
	getline(cin, primaryIndexFileName, '\n');
	if (primaryIndexFileName == "")
		primaryIndexFileName = "primaryindex.txt";

	//Instantiate primary index class with index file name
	//----------------------------------------------------
	PrimaryIndex	primaryIndex(primaryIndexFileName);

	//Prompt user for secondary index and ley list file names
	//-------------------------------------------------------
	cout << "Please enter secondary index file name (default: secondaryindex.txt): ";
	string secondaryIndexFileName = "";
	getline(cin, secondaryIndexFileName, '\n');
	if (secondaryIndexFileName == "")
		secondaryIndexFileName = "secondaryindex.txt";
	cout << "Please enter key list file name (default: keylist.txt): ";
	string keyListFileName = "";
	getline(cin, keyListFileName, '\n');
	if (keyListFileName == "")
		keyListFileName = "keylist.txt";

	//Instantiate secondary index class with index file name and key list file name
	//-----------------------------------------------------------------------------
	SecondaryIndex	secondaryIndex(secondaryIndexFileName, keyListFileName);
	
	
	//Read each record from the data file and insert the student number and byte offset into the primary and secondary indices
	//------------------------------------------------------------------------------------------------------------------------
	string			rawString = "";
	long int		offsetInDataFile = studentDataFile.GetCurrentFilePointerOffset(); //Get offset of first record (i.e. 0)
	while (getline(studentDataFile.dataFileStream, rawString, '\n')) {
		//Read record from data file
		StudentRecord currentStudentRecord(offsetInDataFile, rawString);
		currentStudentRecord.PrintFormatted();

		//Write record to index file
		primaryIndex.Addition(currentStudentRecord.studentNumber, currentStudentRecord.offsetInDataFile);
		secondaryIndex.Addition(currentStudentRecord.lastName, currentStudentRecord.studentNumber, currentStudentRecord.offsetInDataFile);
		
		//Get offset of next record
		offsetInDataFile = studentDataFile.GetCurrentFilePointerOffset();
	}

	//Reporting (debugging purposes)
	//-----------------------------
	fstream reportFileStream("report.txt", ios::out);
	primaryIndex.PrintIndex(reportFileStream);
	secondaryIndex.PrintIndex(reportFileStream);
	secondaryIndex.pKeyList->PrintList(reportFileStream);
	reportFileStream.close();

	//------------------------
	//Step 2: Process searches
	//------------------------
	
	//Prompt user for search file name
	//--------------------------------
	cout << endl
		 << "Please enter search file name (default: mixsearches.txt): ";
	string searchFileName = "";
	getline(cin, searchFileName, '\n');
	if (searchFileName == "")
		searchFileName = "mixsearches.txt";
	cout << endl;
	
	//Open the search file
	//--------------------
	ifstream searchFileStream(searchFileName.c_str(), ios::in);
	if (!searchFileStream) {
		cerr << endl
			 << "------------------------------------------------" << endl
			 << "Error! Specified search file could not be opened!" << endl
			 << "------------------------------------------------" << endl
			 << endl;
		exit(1);
	}
	
	//Read each search request and process it
	//---------------------------------------
	string searchString = "";
	while (getline(searchFileStream, searchString, '\n')) {
		char	prefix = searchString[0];
		string	suffix = searchString.substr(1, searchString.length() - 1);
				
		if (prefix == 's' || prefix == 'S') { //Search primary index by student number
			long int recordOffset = primaryIndex.BinarySearch(suffix);
			if (recordOffset == -1)
				cout << "Record for student number " << suffix << " does not exist." << endl
					<< "-----------------------" << endl
					<< endl;
			else {
				cout << "Search for student number " << suffix << " returned: " << endl;
				studentDataFile.PrintRecordAtOffset(recordOffset);
				cout << endl;
			}
		}
		else if (prefix == 'l' || prefix == 'L') { //Search secondary index by last name
			long int lastNameListStart = secondaryIndex.BinarySearch(suffix);
			if (lastNameListStart == -1)
				cout << "Record for last name " << suffix << " does not exist." << endl
					<< "-----------------------" << endl
					<< endl;
			else {
				cout << "Search for last name " << suffix << " returned: " << endl;
				bool moreInInvertedList = true;
				long int rRNinList = lastNameListStart;
				while (moreInInvertedList) {
					string		secIndexStudentNumber = "";
					long int	secIndexListNext = -2;

					secondaryIndex.pKeyList->ReadByRRN(rRNinList, secIndexStudentNumber, secIndexListNext);
					
					long int recordOffset = primaryIndex.BinarySearch(secIndexStudentNumber);
					if (recordOffset == -1) {
						cerr << endl
							<< "-------------------------------------------------" << endl
							<< "Error! Record found in sec index but not primary!" << endl
							<< "-------------------------------------------------" << endl
							<< endl;
						exit(1);
					}
					else {
						studentDataFile.PrintRecordAtOffset(recordOffset);
						cout << endl;
					}

					if (secIndexListNext == -1) 
						moreInInvertedList = false;
					else
						rRNinList = secIndexListNext;					
				}
			}
		}
		else {
			cerr << endl
				<< "-----------------------------------------------------" << endl
				<< "Error! Specified search file not correctly formatted!" << endl
				<< "-----------------------------------------------------" << endl
				<< endl;
			exit(1);
		}
	}
		
	//Successful termination
	//----------------------
	return 0;
}