/*
 * CSI2131 Winter 2005
 *
 * Assignment#2 Solution : Implementation of The IndexedDatafile class
 *
 * Shantanu Das 
 */


#include "IndexedDatafile.h"


IndexedDatafile::IndexedDatafile(DataFile& x)		//Constructor
{
	dfp = &x;						// set the pointers
	ind = new Index;
	rp = new Record;
}

IndexedDatafile::~IndexedDatafile()				// Destructor 
{
	delete ind;
}

int IndexedDatafile::createIndex()		// creates initial index (returns size of index)
{
	Record &rec=*rp;
	long offset=0;						// variable to calculate the byte offset
	int count=0;
	dfp->GoToStart();					// go to begining of datafile
	while(dfp->readNextRec(rec))
    {
		ind->insert(rec.getkey(), offset);		// insert the new entry to index
		offset += rec.getsize();
		count++;
	}
	cout << "\nCreated Index with " << count << " records." << endl;
	dfp->GoToStart();
	return count;
}

int IndexedDatafile::executeOp(fstream &fs)    // execute operations from file fs
{
	string str,term;
	char c;
	Record& rec=*rp;
	int count = 0;

	while(fs.good() && fs.peek()!=EOF) 
	{
		c=fs.get();						// get the command
		switch(c) {
			case 'S':case 's':			// for search
				while(isspace(fs.peek())) fs.get();	//skip spaces
				getline(fs,str,'+');			// get code
				rec.setcode(str.c_str());
				getline(fs,str,'+');			// get section
				if(str.length() < 1) 
					rec.setsec(' ');
				else rec.setsec(str.at(0));
				getline(fs,term,'+');			// get term
				if(str.length() > 0)
				{
					switch(term.at(0)) {			// this works for Fall/fall/F/f etc.
						case 'F':case 'f':rec.setterm(0);break;
						case 'W':case 'w':rec.setterm(1);break;
						case 'S':case 's':rec.setterm(2);break;
					}
				}
				getline(fs,str);				// get year
				rec.setyear(atoi(str.c_str()));
				search(rec);					// do the search operation
				count++;
				cout<<"\n -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"<<endl;
				cin.get();						// wait for user to press key
				break;
			case 'I':case'i':				// for insert
				getline(fs,str);
				readData(fs,rec);				// read the data to be inserted
				insert(rec);					// do the insert operation
				count++;
				cout<<"\n -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --"<<endl;
				cin.get();						// wait for user to press key
				break;
		}
	}
	return count;
}

void IndexedDatafile::search(Record& rec)			// execute search operation and print results
{
		cout << "\nSearching for ..." <<endl;
		rec.printkey(cout);
		long k = rec.makekey();					// construct key for the record
		long pos = ind->search(k);				// search the index
		if(pos < 0) 
			cout<< "\nRecord Not Found !!!" << endl;
		else {
			if(dfp->getRec(pos,rec)) {				// retrieve the record from datafile
				cout << "\nRecord Found : " << endl;
				rec.printall(cout);
			}
			else cout << "\n Could not retrieve the Record !!!"<< endl;
		}
}

void IndexedDatafile::insert(Record& rec)			// execute insert operation and print results
{
	long k = rec.makekey();
	long pos = ind->search(k);
	if(pos >= 0) {
			cout<< "Duplicate Record : Cannot be inserted !!" << endl;
			rec.printall(cout);
	}
	else {
			pos = dfp->appendRec(rec);		// try to add record to datafile
			if(pos >= 0) {					// successful...
				ind->insert(k,pos);
				cout<< "The following record was inserted successfully..." << endl;
				rec.printall(cout);
			}
			else  cout<< "Error: Could not insert the record !!!" << endl;
	}
}


								
void IndexedDatafile::readData(fstream& fs,Record& rec)
{
								// input the data fields of the record to be inserted
	  string str;
	  char sec = ' ';
	  int year=0,term=0,code1=0,code2=0;
      getline(fs,str);
	  year=atoi(str.c_str());
	  rec.setyear(year);
		
	  getline(fs,str);
	  if(str.compare("Fall")==0)  term=0;
	  else if(str.compare("Winter")==0)  term=1;
	  else if(str.compare("Summer")==0)  term=2;
	  else cerr<< "\nError: Invalid Semester...using default value!" << str << endl;
	  rec.setterm(term);
	
	  getline(fs,str);
	  rec.setcode(str.c_str());

	  getline(fs,str);
	  if(str.length()<=0) sec=' ';
	  else sec = str.at(0);
	  rec.setsec(sec);
	  
	  getline(fs,str);
	  rec.setcname(str.c_str(),str.length());
	  getline(fs,str);
	  rec.setpname(str.c_str(),str.length());
	  getline(fs,str);
	  rec.setclink(str.c_str(),str.length());
	  getline(fs,str);
	  rec.setplink(str.c_str(),str.length());

}