#include "File.h"
#include "Exception.h"
#include <sys/stat.h>
#include <iostream>
#include <sstream>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>

namespace coreutils {

   File::File(coreutils::ZString fileName, int mode, int authority) {
      open(fileName, mode, authority);
   }

   void File::open(coreutils::ZString fileName, int mode, int authority) {

      this->fileName = fileName;

      struct stat status;
      stat(fileName.c_str(), &status);

      buffer = NULL;

      setBufferSize(status.st_size);

      fd = ::open(fileName.c_str(), mode, authority);
      if(fd < 0) {
         std::stringstream temp;
         temp << "Error opening file " << fileName << ".";
         throw Exception(temp.str(), __FILE__, __LINE__);
      }
   }

   File::~File() {
      close(fd);
      free(buffer);
   }

   void File::setBufferSize(size_t size) {
      buffer = (char *)realloc(buffer, size);
      this->size = size;
   }

   int File::read() {
      size = ::read(fd, buffer, size);
      setBufferSize(size);
      return size;
   }

   int File::readLine() {
      setBufferSize(4096);
      size = 0;
      int len = ::read(fd, buffer + size, 1);
      if(len == 0)
        mEof = true;
      while(!mEof && (*(buffer + size) != '\n')) {
         if(*(buffer + size) != '\r') {
//            setBufferSize(size);
            ++size;
         }
         len = ::read(fd, buffer + size, 1);
         if(len == 0)
           mEof = true;
      }
      return size;
   }

   void File::write(std::string data) {
      ::write(fd, data.c_str(), data.length());
   }

   void File::write(coreutils::ZString &data) {
      int len = ::write(fd, data.getData(), data.getLength());
   }

   std::string File::asString() {
      return std::string(buffer, size);
   }

   coreutils::ZString File::asZString() {
      return ZString(buffer, size);
   }

   bool File::eof() {
      return mEof;
   }

}
