#ifndef EFILE_H
#define EFILE_H

#include "eutils.h"

#include "estr.h"
#include "ebuffer.h"
#include <stdio.h>


/*
int efile_size(const estr &filename);

bool efile_exists(const estr &filename);

estr efile_load(const estr &filename);
// More efficient form of passing back all the data
int  efile_load(const estr& filename,estr& buffer);

void efile_save(const estr& filename,const estr& buffer);


void efile_read(FILE *f,estr& buffer);
void efile_gets(FILE *f,estr& buffer);

*/

class evar;

class ebasefile
{
public:
	//  virtual bool open(FILE *fstream,const estr& mode);
	//  bool open(const estr& filename,const estr& mode);
	//  bool open();

	virtual ~ebasefile();

	virtual void close() const = 0;
	virtual void flush() const = 0;

	virtual bool eof() const = 0;

	virtual int write(const estr& str) const = 0;

	virtual int read(estr& str, long int len = -1) const = 0;
	virtual bool readln(estr& str) const = 0;
	virtual bool readarr(estrarray& arr, const estr& sep = estr("\t ")) const = 0;
	virtual bool readarr(estr& line, estrarray& arr, const estr& sep = estr("\t ")) const = 0;
	virtual bool readbuffer(estrbuffer& buffer) const = 0;
};

class eufile
{
private:
	mutable ebasefile *bfile;
public:
	eufile();
	bool open(FILE *fstream, const estr& mode);
	bool open(const estr& filename, const estr& mode);
	bool open(const estr& hostname, const estr& filename, const estr& mode);
	//  bool open();

	void close() const;
	void flush() const;

	bool eof() const;

	int write(const estr& str) const;

	int read(estr& str, long int len = -1) const;
	bool readln(estr& str) const;
	bool readarr(estrarray& arr, const estr& sep = estr("\t ")) const;
	bool readarr(estr& line, estrarray& arr, const estr& sep = estr("\t ")) const;
	bool readbuffer(estrbuffer& buffer) const;
};


#ifdef EUTILS_HAVE_ZLIB_H
#include <zlib.h>

class egzfile : public ebasefile
{
  mutable gzFile f;
  mutable bool opened;
 public:
  estr name;
  mutable estr mode;
  bool blocking;

  egzfile();
  egzfile(const estr& name,const estr& mode);
  ~egzfile();

  bool open(FILE *fstream,const estr& mode);
  bool open(const estr& filename,const estr& mode);
  bool open() const;
//  bool open(const estr& mode);
  void close() const;
  void flush() const;

  bool eof() const;

  int write(const estr& str) const;

  int read(estr& str,long int len=-1) const;
  bool readln(estr& str) const;
  bool readarr(estrarray& arr,const estr& sep=estr("\t ")) const;
  bool readarr(estr& line,estrarray& arr,const estr& sep=estr("\t ")) const;
  bool readbuffer(estrbuffer& buffer) const;
};
#endif

class edcfile : public ebasefile
{
 public:
  bool open(const estr& hostname,const estr& filename,const estr& mode);

  virtual void close() const;
  virtual void flush() const;

  virtual bool eof() const;

  virtual int write(const estr& str) const;

  virtual int read(estr& str,long int len=-1) const;
  virtual bool readln(estr& str) const;
  virtual bool readarr(estrarray& arr,const estr& sep=estr("\t ")) const;
  virtual bool readarr(estr& line,estrarray& arr,const estr& sep=estr("\t ")) const;
  virtual bool readbuffer(estrbuffer& buffer) const;
};

class ehttpfile : public ebasefile
{

};


class efile : public ebasefile
{
  mutable bool opened;
 public:
  mutable FILE* f;

  estr name;
  mutable estr mode;
  bool blocking;

  efile();
  ~efile();

  efile(const efile& file);
  efile(const estr& filename);
  efile(const char* filename);
  efile(char* filename);
  efile(const estr& filename,const estr& mode);
  efile(FILE *file);
  efile(int fd,const estr& mode);

  bool open(FILE *file);
  bool open(int fd,const estr& mode);
  bool open() const;
  bool open(const estr& filename,const estr& mode);
//  bool open(const estr& mode);
  void close() const;
  void flush() const;

  void disableBuffer() const;
  void setNonBlocking() const;
  void wait() const;

  bool create() const;

  estr extension() const;
  estr basename() const;
  estr dirname() const;

  int fileno() const;
  bool eof() const;

  int writevar(const evar& var) const;
//  inline int write(const evar& var) const { return(writevar(var)); }
  int write(const estr& str) const;
  int write(const char *str,int slen) const;
  inline int write(const char *str) const { return(write(str,strlen(str))); }
  inline int write(char *str) const { return(write(str,strlen(str))); }

  evar readvar() const;
  bool readvar(evar& var) const;
  int read(char *str,int slen) const;
  int read(estr& str) const;
  int read(estr& str,long int len) const;
  bool readln(estr& str) const;
  bool readarr(estrarray& arr,const estr& sep=estr("\t ")) const;
  bool readarr(estr& line,estrarray& arr,const estr& sep=estr("\t ")) const;
  bool readbuffer(estrbuffer& buffer) const;


  estrarray grep(const estr& str,const estr& sep="\n") const;
  estrarray egrep(const estr& str,const estr& sep="\n") const;
  estrarray egrepo(const estr& str,const estr& sep="\n") const;
  estr data() const;

  long int size() const;
  long int tell() const;
  int seek(long int p);

  bool exists() const;

  void serial(estr& data) const;
  size_t unserial(const estr& data,size_t i=0);
  void serial(const efile& f) const;
  bool unserial(const efile& f);


  friend void pclose(efile& pfile);
  friend ostream& operator<<(ostream& stream,const efile& file);
};

ostream& operator<<(ostream& stream,const efile& file);


efile popen(const estr& cmd);
void pclose(efile& pfile);
int popen2(const estr& cmd,int& infd,int& outfd);

int system(const estr& cmd);
void showless(const estr& data);

estr dirname(const estr& file);
estr basename(const estr& file);


/*

// Method for reading really large data
const int BUFFER_SIZE=8192;
const int READ_SIZE=4096;

class eafileptr
{
 private:
  int fd;
  char *buffer;
  int   bi,be;
  int   bsize;
  bool  _eof;

  eafileptr();
 public:
  ~eafileptr();
  eafileptr(estr filename);
//  efileptr(FILE *file);
  eafileptr(int fd);

  void open(estr filename);

  inline bool eof() { return(_eof); }
  inline char operator*(){ return(*(buffer+bi)); }
  bool operator++();

  estr getline();
};
*/

#endif

