#include "File.h"

//---------------------------------------------------------------
// Constructor
//---------------------------------------------------------------
File::File(string fn) : current(0)
{
  // Add db data path and db file extension (.DB) to db
  fileName = fn;

  // Open file
  filePtr = fopen(fileName.c_str(),"r");

  // If file exists, calculate file size
  if( filePtr ) {
    fseek(filePtr,0L,SEEK_END);
    fileSize = ftell(filePtr);
    fseek(filePtr,0L,SEEK_SET);
  // Else create a new file 
  } else {
    filePtr = fopen(fileName.c_str(),"w");
    fileSize = 0;
  }
}

//-----------------------------------------------------------
// Destructor
//-----------------------------------------------------------
File::~File() 
{ 
  if( filePtr) fclose(filePtr); 
}

//-----------------------------------------------------------
// Function returns the size of the DBFile in bytes.
//-----------------------------------------------------------
void File::initialize()
{ 
  current = 0;
  fileSize = 0;
  fclose(filePtr);
  remove(fileName.c_str());
  filePtr = fopen(fileName.c_str(),"w");
}

//-----------------------------------------------------------
// Function returns the size of the DBFile in bytes.
//-----------------------------------------------------------
inline int File::getSize()
{ 
  return fileSize; 
}

//-----------------------------------------------------------
// Function returns TRUE if there are more records after 
// after the current pointer in the DBFile, FALSE otherwise.
//-----------------------------------------------------------
inline bool File::hasMoreData() 
{ 
  return (current == fileSize) ? false : true; 
}

//-----------------------------------------------------------
// Function moves internal file pointer to the first record.
//-----------------------------------------------------------
inline void File::first(void) 
{
  if(filePtr) { 
    current = 0;
    fseek(filePtr,0L,SEEK_SET);
  } else {
    throw FileException("first() error");
  }
}

//-----------------------------------------------------------
//  Function moves internal file pointer to the last record.
//-----------------------------------------------------------
inline void File::last(void) 
{
  if(filePtr) fseek(filePtr,0L,SEEK_END);
  else throw FileException("error reading file in last()");
  current = fileSize;
}

//-----------------------------------------------------------
//  Function returns the current record.
//-----------------------------------------------------------
string File::read(void) 
{
  if( current==fileSize ) throw FileException("read() EOF");
  if( !filePtr ) throw FileException("Error reading file");

  int    numChars = 0;
  string s;
  char   c;

  do {
    c = getc(filePtr);
    numChars++;
    s.append(1,c);
  } while( c != '\n' );

  current += numChars;
  fseek(filePtr, current, SEEK_SET);
  return s.substr(0,s.length()-1);
}

//-----------------------------------------------------------
//  Function writes n records to file.
//-----------------------------------------------------------
void File::write(string records[], int n) 
{
  filePtr = freopen(fileName.c_str(),"a",filePtr);
  for(int i=0; i<n; i++) {
    fprintf(filePtr,"%s\n",records[i].c_str());
    fileSize += records[i].length() + 1;
  }
  filePtr = freopen(fileName.c_str(),"r",filePtr);
  current = fileSize;
}

//-----------------------------------------------------------
// Function writes row to file
//-----------------------------------------------------------
void File::write(string row) 
{
  filePtr = freopen(fileName.c_str(),"a",filePtr);
  fprintf(filePtr,"%s\n",row.c_str());
  filePtr = freopen(fileName.c_str(),"r",filePtr);
  fileSize += row.length() + 1;
  current = fileSize;
}

//-----------------------------------------------------------
// Print file
//-----------------------------------------------------------
ostream& operator<< (ostream& os, File& f)
{
  f.first();
  while( f.hasMoreData() ) {
    os << f.read() << endl;
  }
  f.first();
  return os;
}
