// DataFile.cpp
// CSI 2131 Asst 2a by Naim R. El-Far (naim@discover.uottawa.ca)
// CSI 2131 - Winter 2006 - Prof. L.M. Moura

// File:	DataFile.cpp
// Desc:	Class DataFile definitions

#include <iostream>
#include <fstream>
#include <string>
#include "DataFile.h"
#include "StudentRecord.h"
using namespace std;

DataFile::DataFile() { //Default constructor: Initializes data members to default values
	dataFileName = "";
	dataFileStream;
}

DataFile::DataFile(string fileName) {	//Filename constructor: Attach the file stream to the specified file
	dataFileName = fileName;
	dataFileStream.open(fileName.c_str(), ios::in | ios::binary);
	if (!dataFileStream) {
		cerr << endl
			 << "-----------------------------------------------" << endl
			 << "Error! Specified data file could not be opened!" << endl
			 << "-----------------------------------------------" << endl
			 << endl;
		exit(1);
	}
	else
		cout << "Data file " << fileName << " opened successfully." << endl
			 << endl;
}

DataFile::~DataFile() {	//Destructor
	dataFileStream.close();
}

StudentRecord* DataFile::ReadRecordByOffset(long int byteOffset) { //Given an offset in the datafile, retrieve a pointer to the record sitting at that offset
	dataFileStream.clear();
	if (IsLegalOffset(byteOffset)) {
		dataFileStream.seekg(byteOffset);
	}
	else {
		cerr << endl
			 << "---------------------------------" << endl
			 << "Error! Reading outside data file!" << endl
			 << "---------------------------------" << endl
			 << endl;
		exit(1);
	}

	string rawString = "";
	getline(dataFileStream, rawString, '\n');

	StudentRecord*	ptrToRecordFromFile = new StudentRecord(byteOffset, rawString); 
	return ptrToRecordFromFile;
}

long int DataFile::GetCurrentFilePointerOffset() { //We have this method here although it seems redundant because we cannot use the operators == and != for example with tellg, however we can use them with a method that returns tellg's value
	return dataFileStream.tellg();
}

void DataFile::PrintRecordAtOffset(long int offset) { //Given an offset in the data file, print out the record that sits at that offset
	StudentRecord* ptrToStudentRecordFromFile = ReadRecordByOffset(offset);
	StudentRecord* ptrToStudentRecord = new StudentRecord(ptrToStudentRecordFromFile);
	ptrToStudentRecord->PrintFormatted();	
	delete ptrToStudentRecordFromFile;
	delete ptrToStudentRecord;
}

bool DataFile::IsLegalOffset(long int offset) { //This function checks if a given offset is within the data file
	long int positionUponEntry = dataFileStream.tellg();
	dataFileStream.seekg(0, ios::end);
	long int endPosition = dataFileStream.tellg();
	dataFileStream.clear();
	dataFileStream.seekg(positionUponEntry);
	
	if (offset >= 0 && offset <=endPosition) return true;
	else return false;
}