#include "zlib.h"
#include "comp_io.h"

int comp_io_buf::open_file(const char* name, bool stdin_off, int flag)
{
  gzFile fil = nullptr;
  int ret = -1;
  switch (flag)
  {
  case READ:
    if (*name != '\0')
      fil = gzopen(name, "rb");
    else if (!stdin_off)
#ifdef _WIN32
      fil = gzdopen(_fileno(stdin), "rb");
#else
      fil = gzdopen(fileno(stdin), "rb");
#endif
    if (fil != nullptr)
    {
      gz_files.push_back(fil);
      ret = (int)gz_files.size() - 1;
      files.push_back(ret);
    }
    break;

  case WRITE:
    fil = gzopen(name, "wb");
    if (fil != nullptr)
    {
      gz_files.push_back(fil);
      ret = (int)gz_files.size() - 1;
      files.push_back(ret);
    }
    break;

  default:
    std::cerr << "Unknown file operation. Something other than READ/WRITE specified" << std::endl;
  }
  return ret;
}

void comp_io_buf::reset_file(int f)
{
  gzFile fil = gz_files[f];
  gzseek(fil, 0, SEEK_SET);
  space.end() = space.begin();
  head = space.begin();
}

ssize_t comp_io_buf::read_file(int f, void* buf, size_t nbytes)
{
  gzFile fil = gz_files[f];
  int num_read = gzread(fil, buf, (unsigned int)nbytes);
  return (num_read > 0) ? num_read : 0;
}

size_t comp_io_buf::num_files() { return gz_files.size(); }

ssize_t comp_io_buf::write_file(int file, const void* buf, size_t nbytes)
{
  int num_written = gzwrite(gz_files[file], buf, (unsigned int)nbytes);
  return (num_written > 0) ? num_written : 0;
}

bool comp_io_buf::compressed() { return true; }

void comp_io_buf::flush()
{
  if (write_file(0, space.begin(), head - space.end()) != (int)((head - space.end())))
    std::cerr << "error, failed to write to cache\n";
  head = space.begin();
}

bool comp_io_buf::close_file()
{
  if (gz_files.size()>0)
  {
    gzclose(gz_files.back());
    gz_files.pop_back();
    if (files.size() > 0)
      files.pop();
    return true;
  }
  return false;
}
